DWARFFormValue.cpp revision e7285c72793b69f005b5656be9f7aed101cdee4a
1//===-- DWARFFormValue.cpp ------------------------------------------------===//
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 "DWARFFormValue.h"
11#include "DWARFCompileUnit.h"
12#include "DWARFContext.h"
13#include "llvm/Support/Debug.h"
14#include "llvm/Support/Dwarf.h"
15#include "llvm/Support/Format.h"
16#include "llvm/Support/raw_ostream.h"
17#include <cassert>
18using namespace llvm;
19using namespace dwarf;
20
21static const uint8_t form_sizes_addr4[] = {
22  0, // 0x00 unused
23  4, // 0x01 DW_FORM_addr
24  0, // 0x02 unused
25  0, // 0x03 DW_FORM_block2
26  0, // 0x04 DW_FORM_block4
27  2, // 0x05 DW_FORM_data2
28  4, // 0x06 DW_FORM_data4
29  8, // 0x07 DW_FORM_data8
30  0, // 0x08 DW_FORM_string
31  0, // 0x09 DW_FORM_block
32  0, // 0x0a DW_FORM_block1
33  1, // 0x0b DW_FORM_data1
34  1, // 0x0c DW_FORM_flag
35  0, // 0x0d DW_FORM_sdata
36  4, // 0x0e DW_FORM_strp
37  0, // 0x0f DW_FORM_udata
38  4, // 0x10 DW_FORM_ref_addr
39  1, // 0x11 DW_FORM_ref1
40  2, // 0x12 DW_FORM_ref2
41  4, // 0x13 DW_FORM_ref4
42  8, // 0x14 DW_FORM_ref8
43  0, // 0x15 DW_FORM_ref_udata
44  0, // 0x16 DW_FORM_indirect
45  4, // 0x17 DW_FORM_sec_offset
46  0, // 0x18 DW_FORM_exprloc
47  0, // 0x19 DW_FORM_flag_present
48  8, // 0x20 DW_FORM_ref_sig8
49};
50
51static const uint8_t form_sizes_addr8[] = {
52  0, // 0x00 unused
53  8, // 0x01 DW_FORM_addr
54  0, // 0x02 unused
55  0, // 0x03 DW_FORM_block2
56  0, // 0x04 DW_FORM_block4
57  2, // 0x05 DW_FORM_data2
58  4, // 0x06 DW_FORM_data4
59  8, // 0x07 DW_FORM_data8
60  0, // 0x08 DW_FORM_string
61  0, // 0x09 DW_FORM_block
62  0, // 0x0a DW_FORM_block1
63  1, // 0x0b DW_FORM_data1
64  1, // 0x0c DW_FORM_flag
65  0, // 0x0d DW_FORM_sdata
66  4, // 0x0e DW_FORM_strp
67  0, // 0x0f DW_FORM_udata
68  8, // 0x10 DW_FORM_ref_addr
69  1, // 0x11 DW_FORM_ref1
70  2, // 0x12 DW_FORM_ref2
71  4, // 0x13 DW_FORM_ref4
72  8, // 0x14 DW_FORM_ref8
73  0, // 0x15 DW_FORM_ref_udata
74  0, // 0x16 DW_FORM_indirect
75  8, // 0x17 DW_FORM_sec_offset
76  0, // 0x18 DW_FORM_exprloc
77  0, // 0x19 DW_FORM_flag_present
78  8, // 0x20 DW_FORM_ref_sig8
79};
80
81const uint8_t *
82DWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) {
83  switch (addr_size) {
84  case 4: return form_sizes_addr4;
85  case 8: return form_sizes_addr8;
86  }
87  return NULL;
88}
89
90bool
91DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
92                             const DWARFCompileUnit *cu) {
93  bool indirect = false;
94  bool is_block = false;
95  Value.data = NULL;
96  // Read the value for the form into value and follow and DW_FORM_indirect
97  // instances we run into
98  do {
99    indirect = false;
100    switch (Form) {
101    case DW_FORM_addr:
102    case DW_FORM_ref_addr: {
103      RelocAddrMap::const_iterator AI
104        = cu->getRelocMap()->find(*offset_ptr);
105      if (AI != cu->getRelocMap()->end()) {
106        const std::pair<uint8_t, int64_t> &R = AI->second;
107        Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()) +
108                     R.second;
109      } else
110        Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
111      break;
112    }
113    case DW_FORM_exprloc:
114    case DW_FORM_block:
115      Value.uval = data.getULEB128(offset_ptr);
116      is_block = true;
117      break;
118    case DW_FORM_block1:
119      Value.uval = data.getU8(offset_ptr);
120      is_block = true;
121      break;
122    case DW_FORM_block2:
123      Value.uval = data.getU16(offset_ptr);
124      is_block = true;
125      break;
126    case DW_FORM_block4:
127      Value.uval = data.getU32(offset_ptr);
128      is_block = true;
129      break;
130    case DW_FORM_data1:
131    case DW_FORM_ref1:
132    case DW_FORM_flag:
133      Value.uval = data.getU8(offset_ptr);
134      break;
135    case DW_FORM_data2:
136    case DW_FORM_ref2:
137      Value.uval = data.getU16(offset_ptr);
138      break;
139    case DW_FORM_data4:
140    case DW_FORM_ref4:
141      Value.uval = data.getU32(offset_ptr);
142      break;
143    case DW_FORM_data8:
144    case DW_FORM_ref8:
145      Value.uval = data.getU64(offset_ptr);
146      break;
147    case DW_FORM_sdata:
148      Value.sval = data.getSLEB128(offset_ptr);
149      break;
150    case DW_FORM_strp: {
151      RelocAddrMap::const_iterator AI
152        = cu->getRelocMap()->find(*offset_ptr);
153      if (AI != cu->getRelocMap()->end()) {
154        const std::pair<uint8_t, int64_t> &R = AI->second;
155        Value.uval = data.getU32(offset_ptr) + R.second;
156      } else
157        Value.uval = data.getU32(offset_ptr);
158      break;
159    }
160    case DW_FORM_udata:
161    case DW_FORM_ref_udata:
162      Value.uval = data.getULEB128(offset_ptr);
163      break;
164    case DW_FORM_string:
165      Value.cstr = data.getCStr(offset_ptr);
166      // Set the string value to also be the data for inlined cstr form
167      // values only so we can tell the differnence between DW_FORM_string
168      // and DW_FORM_strp form values
169      Value.data = (const uint8_t*)Value.cstr;
170      break;
171    case DW_FORM_indirect:
172      Form = data.getULEB128(offset_ptr);
173      indirect = true;
174      break;
175    case DW_FORM_sec_offset:
176      if (cu->getAddressByteSize() == 4)
177        Value.uval = data.getU32(offset_ptr);
178      else
179        Value.uval = data.getU64(offset_ptr);
180      break;
181    case DW_FORM_flag_present:
182      Value.uval = 1;
183      break;
184    case DW_FORM_ref_sig8:
185      Value.uval = data.getU64(offset_ptr);
186      break;
187    case DW_FORM_GNU_addr_index:
188      Value.uval = data.getULEB128(offset_ptr);
189      break;
190    case DW_FORM_GNU_str_index:
191      Value.uval = data.getULEB128(offset_ptr);
192      break;
193    default:
194      return false;
195    }
196  } while (indirect);
197
198  if (is_block) {
199    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
200    Value.data = NULL;
201    if (!str.empty()) {
202      Value.data = reinterpret_cast<const uint8_t *>(str.data());
203      *offset_ptr += Value.uval;
204    }
205  }
206
207  return true;
208}
209
210bool
211DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
212                          const DWARFCompileUnit *cu) const {
213  return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
214}
215
216bool
217DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
218                          uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
219  bool indirect = false;
220  do {
221    indirect = false;
222    switch (form) {
223    // Blocks if inlined data that have a length field and the data bytes
224    // inlined in the .debug_info
225    case DW_FORM_exprloc:
226    case DW_FORM_block: {
227      uint64_t size = debug_info_data.getULEB128(offset_ptr);
228      *offset_ptr += size;
229      return true;
230    }
231    case DW_FORM_block1: {
232      uint8_t size = debug_info_data.getU8(offset_ptr);
233      *offset_ptr += size;
234      return true;
235    }
236    case DW_FORM_block2: {
237      uint16_t size = debug_info_data.getU16(offset_ptr);
238      *offset_ptr += size;
239      return true;
240    }
241    case DW_FORM_block4: {
242      uint32_t size = debug_info_data.getU32(offset_ptr);
243      *offset_ptr += size;
244      return true;
245    }
246
247    // Inlined NULL terminated C-strings
248    case DW_FORM_string:
249      debug_info_data.getCStr(offset_ptr);
250      return true;
251
252    // Compile unit address sized values
253    case DW_FORM_addr:
254    case DW_FORM_ref_addr:
255      *offset_ptr += cu->getAddressByteSize();
256      return true;
257
258    // 0 byte values - implied from the form.
259    case DW_FORM_flag_present:
260      return true;
261
262    // 1 byte values
263    case DW_FORM_data1:
264    case DW_FORM_flag:
265    case DW_FORM_ref1:
266      *offset_ptr += 1;
267      return true;
268
269    // 2 byte values
270    case DW_FORM_data2:
271    case DW_FORM_ref2:
272      *offset_ptr += 2;
273      return true;
274
275    // 4 byte values
276    case DW_FORM_strp:
277    case DW_FORM_data4:
278    case DW_FORM_ref4:
279      *offset_ptr += 4;
280      return true;
281
282    // 8 byte values
283    case DW_FORM_data8:
284    case DW_FORM_ref8:
285    case DW_FORM_ref_sig8:
286      *offset_ptr += 8;
287      return true;
288
289    // signed or unsigned LEB 128 values
290    //  case DW_FORM_APPLE_db_str:
291    case DW_FORM_sdata:
292    case DW_FORM_udata:
293    case DW_FORM_ref_udata:
294    case DW_FORM_GNU_str_index:
295    case DW_FORM_GNU_addr_index:
296      debug_info_data.getULEB128(offset_ptr);
297      return true;
298
299    case DW_FORM_indirect:
300      indirect = true;
301      form = debug_info_data.getULEB128(offset_ptr);
302      break;
303
304    // 4 for DWARF32, 8 for DWARF64.
305    case DW_FORM_sec_offset:
306      if (cu->getAddressByteSize() == 4)
307        *offset_ptr += 4;
308      else
309        *offset_ptr += 8;
310      return true;
311
312    default:
313      return false;
314    }
315  } while (indirect);
316  return true;
317}
318
319void
320DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
321  DataExtractor debug_str_data(cu->getStringSection(), true, 0);
322  DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
323  uint64_t uvalue = getUnsigned();
324  bool cu_relative_offset = false;
325
326  switch (Form) {
327  case DW_FORM_addr:      OS << format("0x%016" PRIx64, uvalue); break;
328  case DW_FORM_flag_present: OS << "true"; break;
329  case DW_FORM_flag:
330  case DW_FORM_data1:     OS << format("0x%02x", (uint8_t)uvalue); break;
331  case DW_FORM_data2:     OS << format("0x%04x", (uint16_t)uvalue); break;
332  case DW_FORM_data4:     OS << format("0x%08x", (uint32_t)uvalue); break;
333  case DW_FORM_ref_sig8:
334  case DW_FORM_data8:     OS << format("0x%016" PRIx64, uvalue); break;
335  case DW_FORM_string:
336    OS << '"';
337    OS.write_escaped(getAsCString(NULL));
338    OS << '"';
339    break;
340  case DW_FORM_exprloc:
341  case DW_FORM_block:
342  case DW_FORM_block1:
343  case DW_FORM_block2:
344  case DW_FORM_block4:
345    if (uvalue > 0) {
346      switch (Form) {
347      case DW_FORM_exprloc:
348      case DW_FORM_block:  OS << format("<0x%" PRIx64 "> ", uvalue);     break;
349      case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
350      case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
351      case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
352      default: break;
353      }
354
355      const uint8_t* data_ptr = Value.data;
356      if (data_ptr) {
357        // uvalue contains size of block
358        const uint8_t* end_data_ptr = data_ptr + uvalue;
359        while (data_ptr < end_data_ptr) {
360          OS << format("%2.2x ", *data_ptr);
361          ++data_ptr;
362        }
363      }
364      else
365        OS << "NULL";
366    }
367    break;
368
369  case DW_FORM_sdata:     OS << getSigned();   break;
370  case DW_FORM_udata:     OS << getUnsigned(); break;
371  case DW_FORM_strp: {
372    OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
373    const char* dbg_str = getAsCString(&debug_str_data);
374    if (dbg_str) {
375      OS << '"';
376      OS.write_escaped(dbg_str);
377      OS << '"';
378    }
379    break;
380  }
381  case DW_FORM_GNU_str_index: {
382    OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
383    const char *dbg_str = getIndirectCString(&debug_str_data,
384                                             &debug_str_offset_data);
385    if (dbg_str) {
386      OS << '"';
387      OS.write_escaped(dbg_str);
388      OS << '"';
389    }
390    break;
391  }
392  case DW_FORM_ref_addr:
393    OS << format("0x%016" PRIx64, uvalue);
394    break;
395  case DW_FORM_ref1:
396    cu_relative_offset = true;
397    OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
398    break;
399  case DW_FORM_ref2:
400    cu_relative_offset = true;
401    OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
402    break;
403  case DW_FORM_ref4:
404    cu_relative_offset = true;
405    OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
406    break;
407  case DW_FORM_ref8:
408    cu_relative_offset = true;
409    OS << format("cu + 0x%8.8" PRIx64, uvalue);
410    break;
411  case DW_FORM_ref_udata:
412    cu_relative_offset = true;
413    OS << format("cu + 0x%" PRIx64, uvalue);
414    break;
415
416    // All DW_FORM_indirect attributes should be resolved prior to calling
417    // this function
418  case DW_FORM_indirect:
419    OS << "DW_FORM_indirect";
420    break;
421
422  case DW_FORM_sec_offset:
423    if (cu->getAddressByteSize() == 4)
424      OS << format("0x%08x", (uint32_t)uvalue);
425    else
426      OS << format("0x%016" PRIx64, uvalue);
427    break;
428
429  default:
430    OS << format("DW_FORM(0x%4.4x)", Form);
431    break;
432  }
433
434  if (cu_relative_offset)
435    OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
436}
437
438const char*
439DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
440  if (isInlinedCStr()) {
441    return Value.cstr;
442  } else if (debug_str_data_ptr) {
443    uint32_t offset = Value.uval;
444    return debug_str_data_ptr->getCStr(&offset);
445  }
446  return NULL;
447}
448
449const char*
450DWARFFormValue::getIndirectCString(const DataExtractor *DS,
451                                   const DataExtractor *DSO) const {
452  if (!DS || !DSO) return NULL;
453
454  uint32_t offset = Value.uval * 4;
455  uint32_t soffset = DSO->getULEB128(&offset);
456  return DS->getCStr(&soffset);
457}
458
459uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
460  uint64_t die_offset = Value.uval;
461  switch (Form) {
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      die_offset += (cu ? cu->getOffset() : 0);
468      break;
469  default:
470      break;
471  }
472
473  return die_offset;
474}
475
476bool
477DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) {
478  switch (Form) {
479  case DW_FORM_ref1:
480  case DW_FORM_ref2:
481  case DW_FORM_ref4:
482  case DW_FORM_ref8:
483  case DW_FORM_ref_udata:
484    Value.uval += cu->getOffset();
485    Form = DW_FORM_ref_addr;
486    return true;
487  default:
488    break;
489  }
490  return false;
491}
492
493const uint8_t *DWARFFormValue::BlockData() const {
494  if (!isInlinedCStr())
495    return Value.data;
496  return NULL;
497}
498
499bool DWARFFormValue::isBlockForm(uint16_t form) {
500  switch (form) {
501  case DW_FORM_exprloc:
502  case DW_FORM_block:
503  case DW_FORM_block1:
504  case DW_FORM_block2:
505  case DW_FORM_block4:
506    return true;
507  }
508  return false;
509}
510
511bool DWARFFormValue::isDataForm(uint16_t form) {
512  switch (form) {
513  case DW_FORM_sdata:
514  case DW_FORM_udata:
515  case DW_FORM_data1:
516  case DW_FORM_data2:
517  case DW_FORM_data4:
518  case DW_FORM_data8:
519    return true;
520  }
521  return false;
522}
523