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