DWARFFormValue.cpp revision 226584
1226584Sdim//===-- DWARFFormValue.cpp ------------------------------------------------===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim
10226584Sdim#include "DWARFFormValue.h"
11226584Sdim#include "DWARFCompileUnit.h"
12226584Sdim#include "DWARFContext.h"
13226584Sdim#include "llvm/Support/Dwarf.h"
14226584Sdim#include "llvm/Support/Format.h"
15226584Sdim#include "llvm/Support/raw_ostream.h"
16226584Sdim#include <cassert>
17226584Sdimusing namespace llvm;
18226584Sdimusing namespace dwarf;
19226584Sdim
20226584Sdimstatic const uint8_t form_sizes_addr4[] = {
21226584Sdim  0, // 0x00 unused
22226584Sdim  4, // 0x01 DW_FORM_addr
23226584Sdim  0, // 0x02 unused
24226584Sdim  0, // 0x03 DW_FORM_block2
25226584Sdim  0, // 0x04 DW_FORM_block4
26226584Sdim  2, // 0x05 DW_FORM_data2
27226584Sdim  4, // 0x06 DW_FORM_data4
28226584Sdim  8, // 0x07 DW_FORM_data8
29226584Sdim  0, // 0x08 DW_FORM_string
30226584Sdim  0, // 0x09 DW_FORM_block
31226584Sdim  0, // 0x0a DW_FORM_block1
32226584Sdim  1, // 0x0b DW_FORM_data1
33226584Sdim  1, // 0x0c DW_FORM_flag
34226584Sdim  0, // 0x0d DW_FORM_sdata
35226584Sdim  4, // 0x0e DW_FORM_strp
36226584Sdim  0, // 0x0f DW_FORM_udata
37226584Sdim  4, // 0x10 DW_FORM_ref_addr
38226584Sdim  1, // 0x11 DW_FORM_ref1
39226584Sdim  2, // 0x12 DW_FORM_ref2
40226584Sdim  4, // 0x13 DW_FORM_ref4
41226584Sdim  8, // 0x14 DW_FORM_ref8
42226584Sdim  0, // 0x15 DW_FORM_ref_udata
43226584Sdim  0, // 0x16 DW_FORM_indirect
44226584Sdim};
45226584Sdim
46226584Sdimstatic const uint8_t form_sizes_addr8[] = {
47226584Sdim  0, // 0x00 unused
48226584Sdim  8, // 0x01 DW_FORM_addr
49226584Sdim  0, // 0x02 unused
50226584Sdim  0, // 0x03 DW_FORM_block2
51226584Sdim  0, // 0x04 DW_FORM_block4
52226584Sdim  2, // 0x05 DW_FORM_data2
53226584Sdim  4, // 0x06 DW_FORM_data4
54226584Sdim  8, // 0x07 DW_FORM_data8
55226584Sdim  0, // 0x08 DW_FORM_string
56226584Sdim  0, // 0x09 DW_FORM_block
57226584Sdim  0, // 0x0a DW_FORM_block1
58226584Sdim  1, // 0x0b DW_FORM_data1
59226584Sdim  1, // 0x0c DW_FORM_flag
60226584Sdim  0, // 0x0d DW_FORM_sdata
61226584Sdim  4, // 0x0e DW_FORM_strp
62226584Sdim  0, // 0x0f DW_FORM_udata
63226584Sdim  8, // 0x10 DW_FORM_ref_addr
64226584Sdim  1, // 0x11 DW_FORM_ref1
65226584Sdim  2, // 0x12 DW_FORM_ref2
66226584Sdim  4, // 0x13 DW_FORM_ref4
67226584Sdim  8, // 0x14 DW_FORM_ref8
68226584Sdim  0, // 0x15 DW_FORM_ref_udata
69226584Sdim  0, // 0x16 DW_FORM_indirect
70226584Sdim};
71226584Sdim
72226584Sdimconst uint8_t *
73226584SdimDWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) {
74226584Sdim  switch (addr_size) {
75226584Sdim  case 4: return form_sizes_addr4;
76226584Sdim  case 8: return form_sizes_addr8;
77226584Sdim  }
78226584Sdim  return NULL;
79226584Sdim}
80226584Sdim
81226584Sdimbool
82226584SdimDWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
83226584Sdim                             const DWARFCompileUnit *cu) {
84226584Sdim  bool indirect = false;
85226584Sdim  bool is_block = false;
86226584Sdim  Value.data = NULL;
87226584Sdim  // Read the value for the form into value and follow and DW_FORM_indirect
88226584Sdim  // instances we run into
89226584Sdim  do {
90226584Sdim    indirect = false;
91226584Sdim    switch (Form) {
92226584Sdim    case DW_FORM_addr:
93226584Sdim    case DW_FORM_ref_addr:
94226584Sdim      Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
95226584Sdim      break;
96226584Sdim    case DW_FORM_block:
97226584Sdim      Value.uval = data.getULEB128(offset_ptr);
98226584Sdim      is_block = true;
99226584Sdim      break;
100226584Sdim    case DW_FORM_block1:
101226584Sdim      Value.uval = data.getU8(offset_ptr);
102226584Sdim      is_block = true;
103226584Sdim      break;
104226584Sdim    case DW_FORM_block2:
105226584Sdim      Value.uval = data.getU16(offset_ptr);
106226584Sdim      is_block = true;
107226584Sdim      break;
108226584Sdim    case DW_FORM_block4:
109226584Sdim      Value.uval = data.getU32(offset_ptr);
110226584Sdim      is_block = true;
111226584Sdim      break;
112226584Sdim    case DW_FORM_data1:
113226584Sdim    case DW_FORM_ref1:
114226584Sdim    case DW_FORM_flag:
115226584Sdim      Value.uval = data.getU8(offset_ptr);
116226584Sdim      break;
117226584Sdim    case DW_FORM_data2:
118226584Sdim    case DW_FORM_ref2:
119226584Sdim      Value.uval = data.getU16(offset_ptr);
120226584Sdim      break;
121226584Sdim    case DW_FORM_data4:
122226584Sdim    case DW_FORM_ref4:
123226584Sdim      Value.uval = data.getU32(offset_ptr);
124226584Sdim      break;
125226584Sdim    case DW_FORM_data8:
126226584Sdim    case DW_FORM_ref8:
127226584Sdim      Value.uval = data.getU64(offset_ptr);
128226584Sdim      break;
129226584Sdim    case DW_FORM_sdata:
130226584Sdim      Value.sval = data.getSLEB128(offset_ptr);
131226584Sdim      break;
132226584Sdim    case DW_FORM_strp:
133226584Sdim      Value.uval = data.getU32(offset_ptr);
134226584Sdim      break;
135226584Sdim    case DW_FORM_udata:
136226584Sdim    case DW_FORM_ref_udata:
137226584Sdim      Value.uval = data.getULEB128(offset_ptr);
138226584Sdim      break;
139226584Sdim    case DW_FORM_string:
140226584Sdim      Value.cstr = data.getCStr(offset_ptr);
141226584Sdim      // Set the string value to also be the data for inlined cstr form
142226584Sdim      // values only so we can tell the differnence between DW_FORM_string
143226584Sdim      // and DW_FORM_strp form values
144226584Sdim      Value.data = (uint8_t*)Value.cstr;
145226584Sdim      break;
146226584Sdim    case DW_FORM_indirect:
147226584Sdim      Form = data.getULEB128(offset_ptr);
148226584Sdim      indirect = true;
149226584Sdim      break;
150226584Sdim    default:
151226584Sdim      return false;
152226584Sdim    }
153226584Sdim  } while (indirect);
154226584Sdim
155226584Sdim  if (is_block) {
156226584Sdim    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
157226584Sdim    Value.data = NULL;
158226584Sdim    if (!str.empty()) {
159226584Sdim      Value.data = reinterpret_cast<const uint8_t *>(str.data());
160226584Sdim      *offset_ptr += Value.uval;
161226584Sdim    }
162226584Sdim  }
163226584Sdim
164226584Sdim  return true;
165226584Sdim}
166226584Sdim
167226584Sdimbool
168226584SdimDWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
169226584Sdim                          const DWARFCompileUnit *cu) const {
170226584Sdim  return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
171226584Sdim}
172226584Sdim
173226584Sdimbool
174226584SdimDWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
175226584Sdim                          uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
176226584Sdim  bool indirect = false;
177226584Sdim  do {
178226584Sdim    indirect = false;
179226584Sdim    switch (form) {
180226584Sdim    // Blocks if inlined data that have a length field and the data bytes
181226584Sdim    // inlined in the .debug_info
182226584Sdim    case DW_FORM_block: {
183226584Sdim      uint64_t size = debug_info_data.getULEB128(offset_ptr);
184226584Sdim      *offset_ptr += size;
185226584Sdim      return true;
186226584Sdim    }
187226584Sdim    case DW_FORM_block1: {
188226584Sdim      uint8_t size = debug_info_data.getU8(offset_ptr);
189226584Sdim      *offset_ptr += size;
190226584Sdim      return true;
191226584Sdim    }
192226584Sdim    case DW_FORM_block2: {
193226584Sdim      uint16_t size = debug_info_data.getU16(offset_ptr);
194226584Sdim      *offset_ptr += size;
195226584Sdim      return true;
196226584Sdim    }
197226584Sdim    case DW_FORM_block4: {
198226584Sdim      uint32_t size = debug_info_data.getU32(offset_ptr);
199226584Sdim      *offset_ptr += size;
200226584Sdim      return true;
201226584Sdim    }
202226584Sdim
203226584Sdim    // Inlined NULL terminated C-strings
204226584Sdim    case DW_FORM_string:
205226584Sdim      debug_info_data.getCStr(offset_ptr);
206226584Sdim      return true;
207226584Sdim
208226584Sdim    // Compile unit address sized values
209226584Sdim    case DW_FORM_addr:
210226584Sdim    case DW_FORM_ref_addr:
211226584Sdim      *offset_ptr += cu->getAddressByteSize();
212226584Sdim      return true;
213226584Sdim
214226584Sdim    // 1 byte values
215226584Sdim    case DW_FORM_data1:
216226584Sdim    case DW_FORM_flag:
217226584Sdim    case DW_FORM_ref1:
218226584Sdim      *offset_ptr += 1;
219226584Sdim      return true;
220226584Sdim
221226584Sdim    // 2 byte values
222226584Sdim    case DW_FORM_data2:
223226584Sdim    case DW_FORM_ref2:
224226584Sdim      *offset_ptr += 2;
225226584Sdim      return true;
226226584Sdim
227226584Sdim    // 4 byte values
228226584Sdim    case DW_FORM_strp:
229226584Sdim    case DW_FORM_data4:
230226584Sdim    case DW_FORM_ref4:
231226584Sdim      *offset_ptr += 4;
232226584Sdim      return true;
233226584Sdim
234226584Sdim    // 8 byte values
235226584Sdim    case DW_FORM_data8:
236226584Sdim    case DW_FORM_ref8:
237226584Sdim      *offset_ptr += 8;
238226584Sdim      return true;
239226584Sdim
240226584Sdim    // signed or unsigned LEB 128 values
241226584Sdim    //  case DW_FORM_APPLE_db_str:
242226584Sdim    case DW_FORM_sdata:
243226584Sdim    case DW_FORM_udata:
244226584Sdim    case DW_FORM_ref_udata:
245226584Sdim      debug_info_data.getULEB128(offset_ptr);
246226584Sdim      return true;
247226584Sdim
248226584Sdim    case DW_FORM_indirect:
249226584Sdim      indirect = true;
250226584Sdim      form = debug_info_data.getULEB128(offset_ptr);
251226584Sdim      break;
252226584Sdim    default:
253226584Sdim      return false;
254226584Sdim    }
255226584Sdim  } while (indirect);
256226584Sdim  return true;
257226584Sdim}
258226584Sdim
259226584Sdimvoid
260226584SdimDWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
261226584Sdim  DataExtractor debug_str_data(cu->getContext().getStringSection(), true, 0);
262226584Sdim  uint64_t uvalue = getUnsigned();
263226584Sdim  bool cu_relative_offset = false;
264226584Sdim
265226584Sdim  switch (Form) {
266226584Sdim  case DW_FORM_addr:      OS << format("0x%016x", uvalue); break;
267226584Sdim  case DW_FORM_flag:
268226584Sdim  case DW_FORM_data1:     OS << format("0x%02x", uvalue);  break;
269226584Sdim  case DW_FORM_data2:     OS << format("0x%04x", uvalue);  break;
270226584Sdim  case DW_FORM_data4:     OS << format("0x%08x", uvalue);  break;
271226584Sdim  case DW_FORM_data8:     OS << format("0x%016x", uvalue); break;
272226584Sdim  case DW_FORM_string:
273226584Sdim    OS << '"';
274226584Sdim    OS.write_escaped(getAsCString(NULL));
275226584Sdim    OS << '"';
276226584Sdim    break;
277226584Sdim  case DW_FORM_block:
278226584Sdim  case DW_FORM_block1:
279226584Sdim  case DW_FORM_block2:
280226584Sdim  case DW_FORM_block4:
281226584Sdim    if (uvalue > 0) {
282226584Sdim      switch (Form) {
283226584Sdim      case DW_FORM_block:  OS << format("<0x%llx> ", uvalue);            break;
284226584Sdim      case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
285226584Sdim      case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
286226584Sdim      case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
287226584Sdim      default: break;
288226584Sdim      }
289226584Sdim
290226584Sdim      const uint8_t* data_ptr = Value.data;
291226584Sdim      if (data_ptr) {
292226584Sdim        // uvalue contains size of block
293226584Sdim        const uint8_t* end_data_ptr = data_ptr + uvalue;
294226584Sdim        while (data_ptr < end_data_ptr) {
295226584Sdim          OS << format("%2.2x ", *data_ptr);
296226584Sdim          ++data_ptr;
297226584Sdim        }
298226584Sdim      }
299226584Sdim      else
300226584Sdim        OS << "NULL";
301226584Sdim    }
302226584Sdim    break;
303226584Sdim
304226584Sdim  case DW_FORM_sdata:     OS << getSigned();   break;
305226584Sdim  case DW_FORM_udata:     OS << getUnsigned(); break;
306226584Sdim  case DW_FORM_strp: {
307226584Sdim    OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
308226584Sdim    const char* dbg_str = getAsCString(&debug_str_data);
309226584Sdim    if (dbg_str) {
310226584Sdim      OS << '"';
311226584Sdim      OS.write_escaped(dbg_str);
312226584Sdim      OS << '"';
313226584Sdim    }
314226584Sdim    break;
315226584Sdim  }
316226584Sdim  case DW_FORM_ref_addr:
317226584Sdim    OS << format("0x%016x", uvalue);
318226584Sdim    break;
319226584Sdim  case DW_FORM_ref1:
320226584Sdim    cu_relative_offset = true;
321226584Sdim    OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
322226584Sdim    break;
323226584Sdim  case DW_FORM_ref2:
324226584Sdim    cu_relative_offset = true;
325226584Sdim    OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
326226584Sdim    break;
327226584Sdim  case DW_FORM_ref4:
328226584Sdim    cu_relative_offset = true;
329226584Sdim    OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
330226584Sdim    break;
331226584Sdim  case DW_FORM_ref8:
332226584Sdim    cu_relative_offset = true;
333226584Sdim    OS << format("cu + 0x%8.8llx", uvalue);
334226584Sdim    break;
335226584Sdim  case DW_FORM_ref_udata:
336226584Sdim    cu_relative_offset = true;
337226584Sdim    OS << format("cu + 0x%llx", uvalue);
338226584Sdim    break;
339226584Sdim
340226584Sdim    // All DW_FORM_indirect attributes should be resolved prior to calling
341226584Sdim    // this function
342226584Sdim  case DW_FORM_indirect:
343226584Sdim    OS << "DW_FORM_indirect";
344226584Sdim    break;
345226584Sdim  default:
346226584Sdim    OS << format("DW_FORM(0x%4.4x)", Form);
347226584Sdim    break;
348226584Sdim  }
349226584Sdim
350226584Sdim  if (cu_relative_offset)
351226584Sdim    OS << format(" => {0x%8.8x}", (uvalue + (cu ? cu->getOffset() : 0)));
352226584Sdim}
353226584Sdim
354226584Sdimconst char*
355226584SdimDWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
356226584Sdim  if (isInlinedCStr()) {
357226584Sdim    return Value.cstr;
358226584Sdim  } else if (debug_str_data_ptr) {
359226584Sdim    uint32_t offset = Value.uval;
360226584Sdim    return debug_str_data_ptr->getCStr(&offset);
361226584Sdim  }
362226584Sdim  return NULL;
363226584Sdim}
364226584Sdim
365226584Sdimuint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
366226584Sdim  uint64_t die_offset = Value.uval;
367226584Sdim  switch (Form) {
368226584Sdim  case DW_FORM_ref1:
369226584Sdim  case DW_FORM_ref2:
370226584Sdim  case DW_FORM_ref4:
371226584Sdim  case DW_FORM_ref8:
372226584Sdim  case DW_FORM_ref_udata:
373226584Sdim      die_offset += (cu ? cu->getOffset() : 0);
374226584Sdim      break;
375226584Sdim  default:
376226584Sdim      break;
377226584Sdim  }
378226584Sdim
379226584Sdim  return die_offset;
380226584Sdim}
381226584Sdim
382226584Sdimbool
383226584SdimDWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) {
384226584Sdim  switch (Form) {
385226584Sdim  case DW_FORM_ref1:
386226584Sdim  case DW_FORM_ref2:
387226584Sdim  case DW_FORM_ref4:
388226584Sdim  case DW_FORM_ref8:
389226584Sdim  case DW_FORM_ref_udata:
390226584Sdim    Value.uval += cu->getOffset();
391226584Sdim    Form = DW_FORM_ref_addr;
392226584Sdim    return true;
393226584Sdim  default:
394226584Sdim    break;
395226584Sdim  }
396226584Sdim  return false;
397226584Sdim}
398226584Sdim
399226584Sdimconst uint8_t *DWARFFormValue::BlockData() const {
400226584Sdim  if (!isInlinedCStr())
401226584Sdim    return Value.data;
402226584Sdim  return NULL;
403226584Sdim}
404226584Sdim
405226584Sdimbool DWARFFormValue::isBlockForm(uint16_t form) {
406226584Sdim  switch (form) {
407226584Sdim  case DW_FORM_block:
408226584Sdim  case DW_FORM_block1:
409226584Sdim  case DW_FORM_block2:
410226584Sdim  case DW_FORM_block4:
411226584Sdim    return true;
412226584Sdim  }
413226584Sdim  return false;
414226584Sdim}
415226584Sdim
416226584Sdimbool DWARFFormValue::isDataForm(uint16_t form) {
417226584Sdim  switch (form) {
418226584Sdim  case DW_FORM_sdata:
419226584Sdim  case DW_FORM_udata:
420226584Sdim  case DW_FORM_data1:
421226584Sdim  case DW_FORM_data2:
422226584Sdim  case DW_FORM_data4:
423226584Sdim  case DW_FORM_data8:
424226584Sdim    return true;
425226584Sdim  }
426226584Sdim  return false;
427226584Sdim}
428