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  4, // 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      // FIXME: This is 64-bit for DWARF64.
177      Value.uval = data.getU32(offset_ptr);
178      break;
179    case DW_FORM_flag_present:
180      Value.uval = 1;
181      break;
182    case DW_FORM_ref_sig8:
183      Value.uval = data.getU64(offset_ptr);
184      break;
185    case DW_FORM_GNU_addr_index:
186      Value.uval = data.getULEB128(offset_ptr);
187      break;
188    case DW_FORM_GNU_str_index:
189      Value.uval = data.getULEB128(offset_ptr);
190      break;
191    default:
192      return false;
193    }
194  } while (indirect);
195
196  if (is_block) {
197    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
198    Value.data = NULL;
199    if (!str.empty()) {
200      Value.data = reinterpret_cast<const uint8_t *>(str.data());
201      *offset_ptr += Value.uval;
202    }
203  }
204
205  return true;
206}
207
208bool
209DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
210                          const DWARFCompileUnit *cu) const {
211  return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
212}
213
214bool
215DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
216                          uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
217  bool indirect = false;
218  do {
219    indirect = false;
220    switch (form) {
221    // Blocks if inlined data that have a length field and the data bytes
222    // inlined in the .debug_info
223    case DW_FORM_exprloc:
224    case DW_FORM_block: {
225      uint64_t size = debug_info_data.getULEB128(offset_ptr);
226      *offset_ptr += size;
227      return true;
228    }
229    case DW_FORM_block1: {
230      uint8_t size = debug_info_data.getU8(offset_ptr);
231      *offset_ptr += size;
232      return true;
233    }
234    case DW_FORM_block2: {
235      uint16_t size = debug_info_data.getU16(offset_ptr);
236      *offset_ptr += size;
237      return true;
238    }
239    case DW_FORM_block4: {
240      uint32_t size = debug_info_data.getU32(offset_ptr);
241      *offset_ptr += size;
242      return true;
243    }
244
245    // Inlined NULL terminated C-strings
246    case DW_FORM_string:
247      debug_info_data.getCStr(offset_ptr);
248      return true;
249
250    // Compile unit address sized values
251    case DW_FORM_addr:
252    case DW_FORM_ref_addr:
253      *offset_ptr += cu->getAddressByteSize();
254      return true;
255
256    // 0 byte values - implied from the form.
257    case DW_FORM_flag_present:
258      return true;
259
260    // 1 byte values
261    case DW_FORM_data1:
262    case DW_FORM_flag:
263    case DW_FORM_ref1:
264      *offset_ptr += 1;
265      return true;
266
267    // 2 byte values
268    case DW_FORM_data2:
269    case DW_FORM_ref2:
270      *offset_ptr += 2;
271      return true;
272
273    // 4 byte values
274    case DW_FORM_strp:
275    case DW_FORM_data4:
276    case DW_FORM_ref4:
277      *offset_ptr += 4;
278      return true;
279
280    // 8 byte values
281    case DW_FORM_data8:
282    case DW_FORM_ref8:
283    case DW_FORM_ref_sig8:
284      *offset_ptr += 8;
285      return true;
286
287    // signed or unsigned LEB 128 values
288    //  case DW_FORM_APPLE_db_str:
289    case DW_FORM_sdata:
290    case DW_FORM_udata:
291    case DW_FORM_ref_udata:
292    case DW_FORM_GNU_str_index:
293    case DW_FORM_GNU_addr_index:
294      debug_info_data.getULEB128(offset_ptr);
295      return true;
296
297    case DW_FORM_indirect:
298      indirect = true;
299      form = debug_info_data.getULEB128(offset_ptr);
300      break;
301
302    // FIXME: 4 for DWARF32, 8 for DWARF64.
303    case DW_FORM_sec_offset:
304      *offset_ptr += 4;
305      return true;
306
307    default:
308      return false;
309    }
310  } while (indirect);
311  return true;
312}
313
314void
315DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
316  DataExtractor debug_str_data(cu->getStringSection(), true, 0);
317  DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
318  uint64_t uvalue = getUnsigned();
319  bool cu_relative_offset = false;
320
321  switch (Form) {
322  case DW_FORM_addr:      OS << format("0x%016" PRIx64, uvalue); break;
323  case DW_FORM_GNU_addr_index: {
324    StringRef AddrOffsetSec = cu->getAddrOffsetSection();
325    OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
326    if (AddrOffsetSec.size() != 0) {
327      DataExtractor DA(AddrOffsetSec, true, cu->getAddressByteSize());
328      OS << format("0x%016" PRIx64, getIndirectAddress(&DA, cu));
329    } else
330      OS << "<no .debug_addr section>";
331    break;
332  }
333  case DW_FORM_flag_present: OS << "true"; break;
334  case DW_FORM_flag:
335  case DW_FORM_data1:     OS << format("0x%02x", (uint8_t)uvalue); break;
336  case DW_FORM_data2:     OS << format("0x%04x", (uint16_t)uvalue); break;
337  case DW_FORM_data4:     OS << format("0x%08x", (uint32_t)uvalue); break;
338  case DW_FORM_ref_sig8:
339  case DW_FORM_data8:     OS << format("0x%016" PRIx64, uvalue); break;
340  case DW_FORM_string:
341    OS << '"';
342    OS.write_escaped(getAsCString(NULL));
343    OS << '"';
344    break;
345  case DW_FORM_exprloc:
346  case DW_FORM_block:
347  case DW_FORM_block1:
348  case DW_FORM_block2:
349  case DW_FORM_block4:
350    if (uvalue > 0) {
351      switch (Form) {
352      case DW_FORM_exprloc:
353      case DW_FORM_block:  OS << format("<0x%" PRIx64 "> ", uvalue);     break;
354      case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
355      case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
356      case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
357      default: break;
358      }
359
360      const uint8_t* data_ptr = Value.data;
361      if (data_ptr) {
362        // uvalue contains size of block
363        const uint8_t* end_data_ptr = data_ptr + uvalue;
364        while (data_ptr < end_data_ptr) {
365          OS << format("%2.2x ", *data_ptr);
366          ++data_ptr;
367        }
368      }
369      else
370        OS << "NULL";
371    }
372    break;
373
374  case DW_FORM_sdata:     OS << getSigned();   break;
375  case DW_FORM_udata:     OS << getUnsigned(); break;
376  case DW_FORM_strp: {
377    OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
378    const char* dbg_str = getAsCString(&debug_str_data);
379    if (dbg_str) {
380      OS << '"';
381      OS.write_escaped(dbg_str);
382      OS << '"';
383    }
384    break;
385  }
386  case DW_FORM_GNU_str_index: {
387    OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
388    const char *dbg_str = getIndirectCString(&debug_str_data,
389                                             &debug_str_offset_data);
390    if (dbg_str) {
391      OS << '"';
392      OS.write_escaped(dbg_str);
393      OS << '"';
394    }
395    break;
396  }
397  case DW_FORM_ref_addr:
398    OS << format("0x%016" PRIx64, uvalue);
399    break;
400  case DW_FORM_ref1:
401    cu_relative_offset = true;
402    OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
403    break;
404  case DW_FORM_ref2:
405    cu_relative_offset = true;
406    OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
407    break;
408  case DW_FORM_ref4:
409    cu_relative_offset = true;
410    OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
411    break;
412  case DW_FORM_ref8:
413    cu_relative_offset = true;
414    OS << format("cu + 0x%8.8" PRIx64, uvalue);
415    break;
416  case DW_FORM_ref_udata:
417    cu_relative_offset = true;
418    OS << format("cu + 0x%" PRIx64, uvalue);
419    break;
420
421    // All DW_FORM_indirect attributes should be resolved prior to calling
422    // this function
423  case DW_FORM_indirect:
424    OS << "DW_FORM_indirect";
425    break;
426
427    // Should be formatted to 64-bit for DWARF64.
428  case DW_FORM_sec_offset:
429    OS << format("0x%08x", (uint32_t)uvalue);
430    break;
431
432  default:
433    OS << format("DW_FORM(0x%4.4x)", Form);
434    break;
435  }
436
437  if (cu_relative_offset)
438    OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
439}
440
441const char*
442DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
443  if (isInlinedCStr()) {
444    return Value.cstr;
445  } else if (debug_str_data_ptr) {
446    uint32_t offset = Value.uval;
447    return debug_str_data_ptr->getCStr(&offset);
448  }
449  return NULL;
450}
451
452const char*
453DWARFFormValue::getIndirectCString(const DataExtractor *DS,
454                                   const DataExtractor *DSO) const {
455  if (!DS || !DSO) return NULL;
456
457  uint32_t offset = Value.uval * 4;
458  uint32_t soffset = DSO->getU32(&offset);
459  return DS->getCStr(&soffset);
460}
461
462uint64_t
463DWARFFormValue::getIndirectAddress(const DataExtractor *DA,
464                                   const DWARFCompileUnit *cu) const {
465  if (!DA) return 0;
466
467  uint32_t offset = Value.uval * cu->getAddressByteSize();
468  return DA->getAddress(&offset);
469}
470
471uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
472  uint64_t die_offset = Value.uval;
473  switch (Form) {
474  case DW_FORM_ref1:
475  case DW_FORM_ref2:
476  case DW_FORM_ref4:
477  case DW_FORM_ref8:
478  case DW_FORM_ref_udata:
479      die_offset += (cu ? cu->getOffset() : 0);
480      break;
481  default:
482      break;
483  }
484
485  return die_offset;
486}
487
488bool
489DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) {
490  switch (Form) {
491  case DW_FORM_ref1:
492  case DW_FORM_ref2:
493  case DW_FORM_ref4:
494  case DW_FORM_ref8:
495  case DW_FORM_ref_udata:
496    Value.uval += cu->getOffset();
497    Form = DW_FORM_ref_addr;
498    return true;
499  default:
500    break;
501  }
502  return false;
503}
504
505const uint8_t *DWARFFormValue::BlockData() const {
506  if (!isInlinedCStr())
507    return Value.data;
508  return NULL;
509}
510
511bool DWARFFormValue::isBlockForm(uint16_t form) {
512  switch (form) {
513  case DW_FORM_exprloc:
514  case DW_FORM_block:
515  case DW_FORM_block1:
516  case DW_FORM_block2:
517  case DW_FORM_block4:
518    return true;
519  }
520  return false;
521}
522
523bool DWARFFormValue::isDataForm(uint16_t form) {
524  switch (form) {
525  case DW_FORM_sdata:
526  case DW_FORM_udata:
527  case DW_FORM_data1:
528  case DW_FORM_data2:
529  case DW_FORM_data4:
530  case DW_FORM_data8:
531    return true;
532  }
533  return false;
534}
535