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 "llvm/DebugInfo/DWARFFormValue.h"
11#include "DWARFCompileUnit.h"
12#include "DWARFContext.h"
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Debug.h"
16#include "llvm/Support/Dwarf.h"
17#include "llvm/Support/Format.h"
18#include "llvm/Support/raw_ostream.h"
19#include <cassert>
20using namespace llvm;
21using namespace dwarf;
22
23namespace {
24uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
25  // FIXME: Support DWARF64.
26  return (Version == 2) ? AddrSize : 4;
27}
28
29template <uint8_t AddrSize, uint8_t RefAddrSize>
30ArrayRef<uint8_t> makeFixedFormSizesArrayRef() {
31  static const uint8_t sizes[] = {
32    0,           // 0x00 unused
33    AddrSize,    // 0x01 DW_FORM_addr
34    0,           // 0x02 unused
35    0,           // 0x03 DW_FORM_block2
36    0,           // 0x04 DW_FORM_block4
37    2,           // 0x05 DW_FORM_data2
38    4,           // 0x06 DW_FORM_data4
39    8,           // 0x07 DW_FORM_data8
40    0,           // 0x08 DW_FORM_string
41    0,           // 0x09 DW_FORM_block
42    0,           // 0x0a DW_FORM_block1
43    1,           // 0x0b DW_FORM_data1
44    1,           // 0x0c DW_FORM_flag
45    0,           // 0x0d DW_FORM_sdata
46    4,           // 0x0e DW_FORM_strp
47    0,           // 0x0f DW_FORM_udata
48    RefAddrSize, // 0x10 DW_FORM_ref_addr
49    1,           // 0x11 DW_FORM_ref1
50    2,           // 0x12 DW_FORM_ref2
51    4,           // 0x13 DW_FORM_ref4
52    8,           // 0x14 DW_FORM_ref8
53    0,           // 0x15 DW_FORM_ref_udata
54    0,           // 0x16 DW_FORM_indirect
55    4,           // 0x17 DW_FORM_sec_offset
56    0,           // 0x18 DW_FORM_exprloc
57    0,           // 0x19 DW_FORM_flag_present
58  };
59  return makeArrayRef(sizes);
60}
61}
62
63ArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize,
64                                                    uint16_t Version) {
65  uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
66  if (AddrSize == 4 && RefAddrSize == 4)
67    return makeFixedFormSizesArrayRef<4, 4>();
68  if (AddrSize == 4 && RefAddrSize == 8)
69    return makeFixedFormSizesArrayRef<4, 8>();
70  if (AddrSize == 8 && RefAddrSize == 4)
71    return makeFixedFormSizesArrayRef<8, 4>();
72  if (AddrSize == 8 && RefAddrSize == 8)
73    return makeFixedFormSizesArrayRef<8, 8>();
74  return None;
75}
76
77static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
78  DWARFFormValue::FC_Unknown,       // 0x0
79  DWARFFormValue::FC_Address,       // 0x01 DW_FORM_addr
80  DWARFFormValue::FC_Unknown,       // 0x02 unused
81  DWARFFormValue::FC_Block,         // 0x03 DW_FORM_block2
82  DWARFFormValue::FC_Block,         // 0x04 DW_FORM_block4
83  DWARFFormValue::FC_Constant,      // 0x05 DW_FORM_data2
84  // --- These can be FC_SectionOffset in DWARF3 and below:
85  DWARFFormValue::FC_Constant,      // 0x06 DW_FORM_data4
86  DWARFFormValue::FC_Constant,      // 0x07 DW_FORM_data8
87  // ---
88  DWARFFormValue::FC_String,        // 0x08 DW_FORM_string
89  DWARFFormValue::FC_Block,         // 0x09 DW_FORM_block
90  DWARFFormValue::FC_Block,         // 0x0a DW_FORM_block1
91  DWARFFormValue::FC_Constant,      // 0x0b DW_FORM_data1
92  DWARFFormValue::FC_Flag,          // 0x0c DW_FORM_flag
93  DWARFFormValue::FC_Constant,      // 0x0d DW_FORM_sdata
94  DWARFFormValue::FC_String,        // 0x0e DW_FORM_strp
95  DWARFFormValue::FC_Constant,      // 0x0f DW_FORM_udata
96  DWARFFormValue::FC_Reference,     // 0x10 DW_FORM_ref_addr
97  DWARFFormValue::FC_Reference,     // 0x11 DW_FORM_ref1
98  DWARFFormValue::FC_Reference,     // 0x12 DW_FORM_ref2
99  DWARFFormValue::FC_Reference,     // 0x13 DW_FORM_ref4
100  DWARFFormValue::FC_Reference,     // 0x14 DW_FORM_ref8
101  DWARFFormValue::FC_Reference,     // 0x15 DW_FORM_ref_udata
102  DWARFFormValue::FC_Indirect,      // 0x16 DW_FORM_indirect
103  DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
104  DWARFFormValue::FC_Exprloc,       // 0x18 DW_FORM_exprloc
105  DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present
106};
107
108bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
109  // First, check DWARF4 form classes.
110  if (Form < ArrayRef<FormClass>(DWARF4FormClasses).size() &&
111      DWARF4FormClasses[Form] == FC)
112    return true;
113  // Check DW_FORM_ref_sig8 from DWARF4.
114  if (Form == DW_FORM_ref_sig8)
115    return (FC == FC_Reference);
116  // Check for some DWARF5 forms.
117  if (Form == DW_FORM_GNU_addr_index)
118    return (FC == FC_Address);
119  if (Form == DW_FORM_GNU_str_index)
120    return (FC == FC_String);
121  // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
122  // Don't check for DWARF version here, as some producers may still do this
123  // by mistake.
124  if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
125      FC == FC_SectionOffset)
126    return true;
127  return false;
128}
129
130bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
131                                  const DWARFUnit *cu) {
132  bool indirect = false;
133  bool is_block = false;
134  Value.data = nullptr;
135  // Read the value for the form into value and follow and DW_FORM_indirect
136  // instances we run into
137  do {
138    indirect = false;
139    switch (Form) {
140    case DW_FORM_addr:
141    case DW_FORM_ref_addr: {
142      uint16_t AddrSize =
143          (Form == DW_FORM_addr)
144              ? cu->getAddressByteSize()
145              : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
146      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
147      if (AI != cu->getRelocMap()->end()) {
148        const std::pair<uint8_t, int64_t> &R = AI->second;
149        Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
150      } else
151        Value.uval = data.getUnsigned(offset_ptr, AddrSize);
152      break;
153    }
154    case DW_FORM_exprloc:
155    case DW_FORM_block:
156      Value.uval = data.getULEB128(offset_ptr);
157      is_block = true;
158      break;
159    case DW_FORM_block1:
160      Value.uval = data.getU8(offset_ptr);
161      is_block = true;
162      break;
163    case DW_FORM_block2:
164      Value.uval = data.getU16(offset_ptr);
165      is_block = true;
166      break;
167    case DW_FORM_block4:
168      Value.uval = data.getU32(offset_ptr);
169      is_block = true;
170      break;
171    case DW_FORM_data1:
172    case DW_FORM_ref1:
173    case DW_FORM_flag:
174      Value.uval = data.getU8(offset_ptr);
175      break;
176    case DW_FORM_data2:
177    case DW_FORM_ref2:
178      Value.uval = data.getU16(offset_ptr);
179      break;
180    case DW_FORM_data4:
181    case DW_FORM_ref4: {
182      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
183      Value.uval = data.getU32(offset_ptr);
184      if (AI != cu->getRelocMap()->end())
185        Value.uval += AI->second.second;
186      break;
187    }
188    case DW_FORM_data8:
189    case DW_FORM_ref8:
190      Value.uval = data.getU64(offset_ptr);
191      break;
192    case DW_FORM_sdata:
193      Value.sval = data.getSLEB128(offset_ptr);
194      break;
195    case DW_FORM_strp: {
196      RelocAddrMap::const_iterator AI
197        = cu->getRelocMap()->find(*offset_ptr);
198      if (AI != cu->getRelocMap()->end()) {
199        const std::pair<uint8_t, int64_t> &R = AI->second;
200        Value.uval = data.getU32(offset_ptr) + R.second;
201      } else
202        Value.uval = data.getU32(offset_ptr);
203      break;
204    }
205    case DW_FORM_udata:
206    case DW_FORM_ref_udata:
207      Value.uval = data.getULEB128(offset_ptr);
208      break;
209    case DW_FORM_string:
210      Value.cstr = data.getCStr(offset_ptr);
211      break;
212    case DW_FORM_indirect:
213      Form = data.getULEB128(offset_ptr);
214      indirect = true;
215      break;
216    case DW_FORM_sec_offset: {
217      // FIXME: This is 64-bit for DWARF64.
218      RelocAddrMap::const_iterator AI
219        = cu->getRelocMap()->find(*offset_ptr);
220      if (AI != cu->getRelocMap()->end()) {
221        const std::pair<uint8_t, int64_t> &R = AI->second;
222        Value.uval = data.getU32(offset_ptr) + R.second;
223      } else
224        Value.uval = data.getU32(offset_ptr);
225      break;
226    }
227    case DW_FORM_flag_present:
228      Value.uval = 1;
229      break;
230    case DW_FORM_ref_sig8:
231      Value.uval = data.getU64(offset_ptr);
232      break;
233    case DW_FORM_GNU_addr_index:
234    case DW_FORM_GNU_str_index:
235      Value.uval = data.getULEB128(offset_ptr);
236      break;
237    default:
238      return false;
239    }
240  } while (indirect);
241
242  if (is_block) {
243    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
244    Value.data = nullptr;
245    if (!str.empty()) {
246      Value.data = reinterpret_cast<const uint8_t *>(str.data());
247      *offset_ptr += Value.uval;
248    }
249  }
250
251  return true;
252}
253
254bool
255DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
256                          const DWARFUnit *cu) const {
257  return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
258}
259
260bool
261DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
262                          uint32_t *offset_ptr, const DWARFUnit *cu) {
263  bool indirect = false;
264  do {
265    switch (form) {
266    // Blocks if inlined data that have a length field and the data bytes
267    // inlined in the .debug_info
268    case DW_FORM_exprloc:
269    case DW_FORM_block: {
270      uint64_t size = debug_info_data.getULEB128(offset_ptr);
271      *offset_ptr += size;
272      return true;
273    }
274    case DW_FORM_block1: {
275      uint8_t size = debug_info_data.getU8(offset_ptr);
276      *offset_ptr += size;
277      return true;
278    }
279    case DW_FORM_block2: {
280      uint16_t size = debug_info_data.getU16(offset_ptr);
281      *offset_ptr += size;
282      return true;
283    }
284    case DW_FORM_block4: {
285      uint32_t size = debug_info_data.getU32(offset_ptr);
286      *offset_ptr += size;
287      return true;
288    }
289
290    // Inlined NULL terminated C-strings
291    case DW_FORM_string:
292      debug_info_data.getCStr(offset_ptr);
293      return true;
294
295    // Compile unit address sized values
296    case DW_FORM_addr:
297      *offset_ptr += cu->getAddressByteSize();
298      return true;
299    case DW_FORM_ref_addr:
300      *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
301      return true;
302
303    // 0 byte values - implied from the form.
304    case DW_FORM_flag_present:
305      return true;
306
307    // 1 byte values
308    case DW_FORM_data1:
309    case DW_FORM_flag:
310    case DW_FORM_ref1:
311      *offset_ptr += 1;
312      return true;
313
314    // 2 byte values
315    case DW_FORM_data2:
316    case DW_FORM_ref2:
317      *offset_ptr += 2;
318      return true;
319
320    // 4 byte values
321    case DW_FORM_strp:
322    case DW_FORM_data4:
323    case DW_FORM_ref4:
324      *offset_ptr += 4;
325      return true;
326
327    // 8 byte values
328    case DW_FORM_data8:
329    case DW_FORM_ref8:
330    case DW_FORM_ref_sig8:
331      *offset_ptr += 8;
332      return true;
333
334    // signed or unsigned LEB 128 values
335    //  case DW_FORM_APPLE_db_str:
336    case DW_FORM_sdata:
337    case DW_FORM_udata:
338    case DW_FORM_ref_udata:
339    case DW_FORM_GNU_str_index:
340    case DW_FORM_GNU_addr_index:
341      debug_info_data.getULEB128(offset_ptr);
342      return true;
343
344    case DW_FORM_indirect:
345      indirect = true;
346      form = debug_info_data.getULEB128(offset_ptr);
347      break;
348
349    // FIXME: 4 for DWARF32, 8 for DWARF64.
350    case DW_FORM_sec_offset:
351      *offset_ptr += 4;
352      return true;
353
354    default:
355      return false;
356    }
357  } while (indirect);
358  return true;
359}
360
361void
362DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
363  DataExtractor debug_str_data(cu->getStringSection(), true, 0);
364  DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
365  uint64_t uvalue = Value.uval;
366  bool cu_relative_offset = false;
367
368  switch (Form) {
369  case DW_FORM_addr:      OS << format("0x%016" PRIx64, uvalue); break;
370  case DW_FORM_GNU_addr_index: {
371    OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
372    uint64_t Address;
373    if (cu->getAddrOffsetSectionItem(uvalue, Address))
374      OS << format("0x%016" PRIx64, Address);
375    else
376      OS << "<no .debug_addr section>";
377    break;
378  }
379  case DW_FORM_flag_present: OS << "true"; break;
380  case DW_FORM_flag:
381  case DW_FORM_data1:     OS << format("0x%02x", (uint8_t)uvalue); break;
382  case DW_FORM_data2:     OS << format("0x%04x", (uint16_t)uvalue); break;
383  case DW_FORM_data4:     OS << format("0x%08x", (uint32_t)uvalue); break;
384  case DW_FORM_ref_sig8:
385  case DW_FORM_data8:     OS << format("0x%016" PRIx64, uvalue); break;
386  case DW_FORM_string:
387    OS << '"';
388    OS.write_escaped(Value.cstr);
389    OS << '"';
390    break;
391  case DW_FORM_exprloc:
392  case DW_FORM_block:
393  case DW_FORM_block1:
394  case DW_FORM_block2:
395  case DW_FORM_block4:
396    if (uvalue > 0) {
397      switch (Form) {
398      case DW_FORM_exprloc:
399      case DW_FORM_block:  OS << format("<0x%" PRIx64 "> ", uvalue);     break;
400      case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
401      case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
402      case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
403      default: break;
404      }
405
406      const uint8_t* data_ptr = Value.data;
407      if (data_ptr) {
408        // uvalue contains size of block
409        const uint8_t* end_data_ptr = data_ptr + uvalue;
410        while (data_ptr < end_data_ptr) {
411          OS << format("%2.2x ", *data_ptr);
412          ++data_ptr;
413        }
414      }
415      else
416        OS << "NULL";
417    }
418    break;
419
420  case DW_FORM_sdata:     OS << Value.sval; break;
421  case DW_FORM_udata:     OS << Value.uval; break;
422  case DW_FORM_strp: {
423    OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
424    Optional<const char *> DbgStr = getAsCString(cu);
425    if (DbgStr.hasValue()) {
426      OS << '"';
427      OS.write_escaped(DbgStr.getValue());
428      OS << '"';
429    }
430    break;
431  }
432  case DW_FORM_GNU_str_index: {
433    OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
434    Optional<const char *> DbgStr = getAsCString(cu);
435    if (DbgStr.hasValue()) {
436      OS << '"';
437      OS.write_escaped(DbgStr.getValue());
438      OS << '"';
439    }
440    break;
441  }
442  case DW_FORM_ref_addr:
443    OS << format("0x%016" PRIx64, uvalue);
444    break;
445  case DW_FORM_ref1:
446    cu_relative_offset = true;
447    OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
448    break;
449  case DW_FORM_ref2:
450    cu_relative_offset = true;
451    OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
452    break;
453  case DW_FORM_ref4:
454    cu_relative_offset = true;
455    OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
456    break;
457  case DW_FORM_ref8:
458    cu_relative_offset = true;
459    OS << format("cu + 0x%8.8" PRIx64, uvalue);
460    break;
461  case DW_FORM_ref_udata:
462    cu_relative_offset = true;
463    OS << format("cu + 0x%" PRIx64, uvalue);
464    break;
465
466    // All DW_FORM_indirect attributes should be resolved prior to calling
467    // this function
468  case DW_FORM_indirect:
469    OS << "DW_FORM_indirect";
470    break;
471
472    // Should be formatted to 64-bit for DWARF64.
473  case DW_FORM_sec_offset:
474    OS << format("0x%08x", (uint32_t)uvalue);
475    break;
476
477  default:
478    OS << format("DW_FORM(0x%4.4x)", Form);
479    break;
480  }
481
482  if (cu_relative_offset)
483    OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
484}
485
486Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
487  if (!isFormClass(FC_String))
488    return None;
489  if (Form == DW_FORM_string)
490    return Value.cstr;
491  if (!U)
492    return None;
493  uint32_t Offset = Value.uval;
494  if (Form == DW_FORM_GNU_str_index) {
495    uint32_t StrOffset;
496    if (!U->getStringOffsetSectionItem(Offset, StrOffset))
497      return None;
498    Offset = StrOffset;
499  }
500  if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
501    return Str;
502  }
503  return None;
504}
505
506Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
507  if (!isFormClass(FC_Address))
508    return None;
509  if (Form == DW_FORM_GNU_addr_index) {
510    uint32_t Index = Value.uval;
511    uint64_t Result;
512    if (!U || !U->getAddrOffsetSectionItem(Index, Result))
513      return None;
514    return Result;
515  }
516  return Value.uval;
517}
518
519Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
520  if (!isFormClass(FC_Reference))
521    return None;
522  switch (Form) {
523  case DW_FORM_ref1:
524  case DW_FORM_ref2:
525  case DW_FORM_ref4:
526  case DW_FORM_ref8:
527  case DW_FORM_ref_udata:
528    if (!U)
529      return None;
530    return Value.uval + U->getOffset();
531  case DW_FORM_ref_addr:
532    return Value.uval;
533  // FIXME: Add proper support for DW_FORM_ref_sig8
534  default:
535    return Value.uval;
536  }
537}
538
539Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
540  if (!isFormClass(FC_SectionOffset))
541    return None;
542  return Value.uval;
543}
544
545Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
546  if (!isFormClass(FC_Constant) || Form == DW_FORM_sdata)
547    return None;
548  return Value.uval;
549}
550