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