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