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