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
10252723Sdim#include "llvm/DebugInfo/DWARFFormValue.h"
11226584Sdim#include "DWARFCompileUnit.h"
12226584Sdim#include "DWARFContext.h"
13263509Sdim#include "llvm/ADT/ArrayRef.h"
14263509Sdim#include "llvm/ADT/StringRef.h"
15245431Sdim#include "llvm/Support/Debug.h"
16226584Sdim#include "llvm/Support/Dwarf.h"
17226584Sdim#include "llvm/Support/Format.h"
18226584Sdim#include "llvm/Support/raw_ostream.h"
19226584Sdim#include <cassert>
20226584Sdimusing namespace llvm;
21226584Sdimusing namespace dwarf;
22226584Sdim
23252723Sdimnamespace {
24263509Sdimuint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
25263509Sdim  // FIXME: Support DWARF64.
26263509Sdim  return (Version == 2) ? AddrSize : 4;
27252723Sdim}
28226584Sdim
29252723Sdimtemplate <uint8_t AddrSize, uint8_t RefAddrSize>
30263509SdimArrayRef<uint8_t> makeFixedFormSizesArrayRef() {
31263509Sdim  static const uint8_t sizes[] = {
32263509Sdim    0,           // 0x00 unused
33263509Sdim    AddrSize,    // 0x01 DW_FORM_addr
34263509Sdim    0,           // 0x02 unused
35263509Sdim    0,           // 0x03 DW_FORM_block2
36263509Sdim    0,           // 0x04 DW_FORM_block4
37263509Sdim    2,           // 0x05 DW_FORM_data2
38263509Sdim    4,           // 0x06 DW_FORM_data4
39263509Sdim    8,           // 0x07 DW_FORM_data8
40263509Sdim    0,           // 0x08 DW_FORM_string
41263509Sdim    0,           // 0x09 DW_FORM_block
42263509Sdim    0,           // 0x0a DW_FORM_block1
43263509Sdim    1,           // 0x0b DW_FORM_data1
44263509Sdim    1,           // 0x0c DW_FORM_flag
45263509Sdim    0,           // 0x0d DW_FORM_sdata
46263509Sdim    4,           // 0x0e DW_FORM_strp
47263509Sdim    0,           // 0x0f DW_FORM_udata
48263509Sdim    RefAddrSize, // 0x10 DW_FORM_ref_addr
49263509Sdim    1,           // 0x11 DW_FORM_ref1
50263509Sdim    2,           // 0x12 DW_FORM_ref2
51263509Sdim    4,           // 0x13 DW_FORM_ref4
52263509Sdim    8,           // 0x14 DW_FORM_ref8
53263509Sdim    0,           // 0x15 DW_FORM_ref_udata
54263509Sdim    0,           // 0x16 DW_FORM_indirect
55263509Sdim    4,           // 0x17 DW_FORM_sec_offset
56263509Sdim    0,           // 0x18 DW_FORM_exprloc
57263509Sdim    0,           // 0x19 DW_FORM_flag_present
58263509Sdim  };
59263509Sdim  return makeArrayRef(sizes);
60252723Sdim}
61263509Sdim}
62252723Sdim
63263509SdimArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize,
64263509Sdim                                                    uint16_t Version) {
65252723Sdim  uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
66252723Sdim  if (AddrSize == 4 && RefAddrSize == 4)
67263509Sdim    return makeFixedFormSizesArrayRef<4, 4>();
68252723Sdim  if (AddrSize == 4 && RefAddrSize == 8)
69263509Sdim    return makeFixedFormSizesArrayRef<4, 8>();
70252723Sdim  if (AddrSize == 8 && RefAddrSize == 4)
71263509Sdim    return makeFixedFormSizesArrayRef<8, 4>();
72252723Sdim  if (AddrSize == 8 && RefAddrSize == 8)
73263509Sdim    return makeFixedFormSizesArrayRef<8, 8>();
74263509Sdim  return None;
75226584Sdim}
76226584Sdim
77263509Sdimstatic const DWARFFormValue::FormClass DWARF4FormClasses[] = {
78263509Sdim  DWARFFormValue::FC_Unknown,       // 0x0
79263509Sdim  DWARFFormValue::FC_Address,       // 0x01 DW_FORM_addr
80263509Sdim  DWARFFormValue::FC_Unknown,       // 0x02 unused
81263509Sdim  DWARFFormValue::FC_Block,         // 0x03 DW_FORM_block2
82263509Sdim  DWARFFormValue::FC_Block,         // 0x04 DW_FORM_block4
83263509Sdim  DWARFFormValue::FC_Constant,      // 0x05 DW_FORM_data2
84263509Sdim  // --- These can be FC_SectionOffset in DWARF3 and below:
85263509Sdim  DWARFFormValue::FC_Constant,      // 0x06 DW_FORM_data4
86263509Sdim  DWARFFormValue::FC_Constant,      // 0x07 DW_FORM_data8
87263509Sdim  // ---
88263509Sdim  DWARFFormValue::FC_String,        // 0x08 DW_FORM_string
89263509Sdim  DWARFFormValue::FC_Block,         // 0x09 DW_FORM_block
90263509Sdim  DWARFFormValue::FC_Block,         // 0x0a DW_FORM_block1
91263509Sdim  DWARFFormValue::FC_Constant,      // 0x0b DW_FORM_data1
92263509Sdim  DWARFFormValue::FC_Flag,          // 0x0c DW_FORM_flag
93263509Sdim  DWARFFormValue::FC_Constant,      // 0x0d DW_FORM_sdata
94263509Sdim  DWARFFormValue::FC_String,        // 0x0e DW_FORM_strp
95263509Sdim  DWARFFormValue::FC_Constant,      // 0x0f DW_FORM_udata
96263509Sdim  DWARFFormValue::FC_Reference,     // 0x10 DW_FORM_ref_addr
97263509Sdim  DWARFFormValue::FC_Reference,     // 0x11 DW_FORM_ref1
98263509Sdim  DWARFFormValue::FC_Reference,     // 0x12 DW_FORM_ref2
99263509Sdim  DWARFFormValue::FC_Reference,     // 0x13 DW_FORM_ref4
100263509Sdim  DWARFFormValue::FC_Reference,     // 0x14 DW_FORM_ref8
101263509Sdim  DWARFFormValue::FC_Reference,     // 0x15 DW_FORM_ref_udata
102263509Sdim  DWARFFormValue::FC_Indirect,      // 0x16 DW_FORM_indirect
103263509Sdim  DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
104263509Sdim  DWARFFormValue::FC_Exprloc,       // 0x18 DW_FORM_exprloc
105263509Sdim  DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present
106263509Sdim};
107263509Sdim
108263509Sdimbool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
109263509Sdim  // First, check DWARF4 form classes.
110263509Sdim  if (Form < ArrayRef<FormClass>(DWARF4FormClasses).size() &&
111263509Sdim      DWARF4FormClasses[Form] == FC)
112263509Sdim    return true;
113263509Sdim  // Check DW_FORM_ref_sig8 from DWARF4.
114263509Sdim  if (Form == DW_FORM_ref_sig8)
115263509Sdim    return (FC == FC_Reference);
116263509Sdim  // Check for some DWARF5 forms.
117263509Sdim  if (Form == DW_FORM_GNU_addr_index)
118263509Sdim    return (FC == FC_Address);
119263509Sdim  if (Form == DW_FORM_GNU_str_index)
120263509Sdim    return (FC == FC_String);
121263509Sdim  // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
122263509Sdim  // Don't check for DWARF version here, as some producers may still do this
123263509Sdim  // by mistake.
124263509Sdim  if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
125263509Sdim      FC == FC_SectionOffset)
126263509Sdim    return true;
127263509Sdim  return false;
128263509Sdim}
129263509Sdim
130263509Sdimbool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
131263509Sdim                                  const DWARFUnit *cu) {
132226584Sdim  bool indirect = false;
133226584Sdim  bool is_block = false;
134226584Sdim  Value.data = NULL;
135226584Sdim  // Read the value for the form into value and follow and DW_FORM_indirect
136226584Sdim  // instances we run into
137226584Sdim  do {
138226584Sdim    indirect = false;
139226584Sdim    switch (Form) {
140226584Sdim    case DW_FORM_addr:
141245431Sdim    case DW_FORM_ref_addr: {
142252723Sdim      uint16_t AddrSize =
143252723Sdim          (Form == DW_FORM_addr)
144252723Sdim              ? cu->getAddressByteSize()
145252723Sdim              : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
146252723Sdim      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
147252723Sdim      if (AI != cu->getRelocMap()->end()) {
148245431Sdim        const std::pair<uint8_t, int64_t> &R = AI->second;
149252723Sdim        Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
150245431Sdim      } else
151252723Sdim        Value.uval = data.getUnsigned(offset_ptr, AddrSize);
152252723Sdim      break;
153245431Sdim    }
154245431Sdim    case DW_FORM_exprloc:
155226584Sdim    case DW_FORM_block:
156226584Sdim      Value.uval = data.getULEB128(offset_ptr);
157226584Sdim      is_block = true;
158226584Sdim      break;
159226584Sdim    case DW_FORM_block1:
160226584Sdim      Value.uval = data.getU8(offset_ptr);
161226584Sdim      is_block = true;
162226584Sdim      break;
163226584Sdim    case DW_FORM_block2:
164226584Sdim      Value.uval = data.getU16(offset_ptr);
165226584Sdim      is_block = true;
166226584Sdim      break;
167226584Sdim    case DW_FORM_block4:
168226584Sdim      Value.uval = data.getU32(offset_ptr);
169226584Sdim      is_block = true;
170226584Sdim      break;
171226584Sdim    case DW_FORM_data1:
172226584Sdim    case DW_FORM_ref1:
173226584Sdim    case DW_FORM_flag:
174226584Sdim      Value.uval = data.getU8(offset_ptr);
175226584Sdim      break;
176226584Sdim    case DW_FORM_data2:
177226584Sdim    case DW_FORM_ref2:
178226584Sdim      Value.uval = data.getU16(offset_ptr);
179226584Sdim      break;
180226584Sdim    case DW_FORM_data4:
181263509Sdim    case DW_FORM_ref4: {
182263509Sdim      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
183226584Sdim      Value.uval = data.getU32(offset_ptr);
184263509Sdim      if (AI != cu->getRelocMap()->end())
185263509Sdim        Value.uval += AI->second.second;
186226584Sdim      break;
187263509Sdim    }
188226584Sdim    case DW_FORM_data8:
189226584Sdim    case DW_FORM_ref8:
190226584Sdim      Value.uval = data.getU64(offset_ptr);
191226584Sdim      break;
192226584Sdim    case DW_FORM_sdata:
193226584Sdim      Value.sval = data.getSLEB128(offset_ptr);
194226584Sdim      break;
195245431Sdim    case DW_FORM_strp: {
196245431Sdim      RelocAddrMap::const_iterator AI
197252723Sdim        = cu->getRelocMap()->find(*offset_ptr);
198252723Sdim      if (AI != cu->getRelocMap()->end()) {
199245431Sdim        const std::pair<uint8_t, int64_t> &R = AI->second;
200252723Sdim        Value.uval = data.getU32(offset_ptr) + R.second;
201245431Sdim      } else
202245431Sdim        Value.uval = data.getU32(offset_ptr);
203226584Sdim      break;
204245431Sdim    }
205226584Sdim    case DW_FORM_udata:
206226584Sdim    case DW_FORM_ref_udata:
207226584Sdim      Value.uval = data.getULEB128(offset_ptr);
208226584Sdim      break;
209226584Sdim    case DW_FORM_string:
210226584Sdim      Value.cstr = data.getCStr(offset_ptr);
211226584Sdim      break;
212226584Sdim    case DW_FORM_indirect:
213226584Sdim      Form = data.getULEB128(offset_ptr);
214226584Sdim      indirect = true;
215226584Sdim      break;
216252723Sdim    case DW_FORM_sec_offset: {
217252723Sdim      // FIXME: This is 64-bit for DWARF64.
218252723Sdim      RelocAddrMap::const_iterator AI
219252723Sdim        = cu->getRelocMap()->find(*offset_ptr);
220252723Sdim      if (AI != cu->getRelocMap()->end()) {
221252723Sdim        const std::pair<uint8_t, int64_t> &R = AI->second;
222252723Sdim        Value.uval = data.getU32(offset_ptr) + R.second;
223252723Sdim      } else
224245431Sdim        Value.uval = data.getU32(offset_ptr);
225245431Sdim      break;
226252723Sdim    }
227245431Sdim    case DW_FORM_flag_present:
228245431Sdim      Value.uval = 1;
229245431Sdim      break;
230245431Sdim    case DW_FORM_ref_sig8:
231245431Sdim      Value.uval = data.getU64(offset_ptr);
232245431Sdim      break;
233252723Sdim    case DW_FORM_GNU_addr_index:
234252723Sdim    case DW_FORM_GNU_str_index:
235252723Sdim      Value.uval = data.getULEB128(offset_ptr);
236252723Sdim      break;
237226584Sdim    default:
238226584Sdim      return false;
239226584Sdim    }
240226584Sdim  } while (indirect);
241226584Sdim
242226584Sdim  if (is_block) {
243226584Sdim    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
244226584Sdim    Value.data = NULL;
245226584Sdim    if (!str.empty()) {
246226584Sdim      Value.data = reinterpret_cast<const uint8_t *>(str.data());
247226584Sdim      *offset_ptr += Value.uval;
248226584Sdim    }
249226584Sdim  }
250226584Sdim
251226584Sdim  return true;
252226584Sdim}
253226584Sdim
254226584Sdimbool
255226584SdimDWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
256263509Sdim                          const DWARFUnit *cu) const {
257226584Sdim  return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
258226584Sdim}
259226584Sdim
260226584Sdimbool
261226584SdimDWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
262263509Sdim                          uint32_t *offset_ptr, const DWARFUnit *cu) {
263226584Sdim  bool indirect = false;
264226584Sdim  do {
265226584Sdim    switch (form) {
266226584Sdim    // Blocks if inlined data that have a length field and the data bytes
267226584Sdim    // inlined in the .debug_info
268245431Sdim    case DW_FORM_exprloc:
269226584Sdim    case DW_FORM_block: {
270226584Sdim      uint64_t size = debug_info_data.getULEB128(offset_ptr);
271226584Sdim      *offset_ptr += size;
272226584Sdim      return true;
273226584Sdim    }
274226584Sdim    case DW_FORM_block1: {
275226584Sdim      uint8_t size = debug_info_data.getU8(offset_ptr);
276226584Sdim      *offset_ptr += size;
277226584Sdim      return true;
278226584Sdim    }
279226584Sdim    case DW_FORM_block2: {
280226584Sdim      uint16_t size = debug_info_data.getU16(offset_ptr);
281226584Sdim      *offset_ptr += size;
282226584Sdim      return true;
283226584Sdim    }
284226584Sdim    case DW_FORM_block4: {
285226584Sdim      uint32_t size = debug_info_data.getU32(offset_ptr);
286226584Sdim      *offset_ptr += size;
287226584Sdim      return true;
288226584Sdim    }
289226584Sdim
290226584Sdim    // Inlined NULL terminated C-strings
291226584Sdim    case DW_FORM_string:
292226584Sdim      debug_info_data.getCStr(offset_ptr);
293226584Sdim      return true;
294226584Sdim
295226584Sdim    // Compile unit address sized values
296226584Sdim    case DW_FORM_addr:
297226584Sdim      *offset_ptr += cu->getAddressByteSize();
298226584Sdim      return true;
299252723Sdim    case DW_FORM_ref_addr:
300252723Sdim      *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
301252723Sdim      return true;
302226584Sdim
303245431Sdim    // 0 byte values - implied from the form.
304245431Sdim    case DW_FORM_flag_present:
305245431Sdim      return true;
306252723Sdim
307226584Sdim    // 1 byte values
308226584Sdim    case DW_FORM_data1:
309226584Sdim    case DW_FORM_flag:
310226584Sdim    case DW_FORM_ref1:
311226584Sdim      *offset_ptr += 1;
312226584Sdim      return true;
313226584Sdim
314226584Sdim    // 2 byte values
315226584Sdim    case DW_FORM_data2:
316226584Sdim    case DW_FORM_ref2:
317226584Sdim      *offset_ptr += 2;
318226584Sdim      return true;
319226584Sdim
320226584Sdim    // 4 byte values
321226584Sdim    case DW_FORM_strp:
322226584Sdim    case DW_FORM_data4:
323226584Sdim    case DW_FORM_ref4:
324226584Sdim      *offset_ptr += 4;
325226584Sdim      return true;
326226584Sdim
327226584Sdim    // 8 byte values
328226584Sdim    case DW_FORM_data8:
329226584Sdim    case DW_FORM_ref8:
330245431Sdim    case DW_FORM_ref_sig8:
331226584Sdim      *offset_ptr += 8;
332226584Sdim      return true;
333226584Sdim
334226584Sdim    // signed or unsigned LEB 128 values
335226584Sdim    //  case DW_FORM_APPLE_db_str:
336226584Sdim    case DW_FORM_sdata:
337226584Sdim    case DW_FORM_udata:
338226584Sdim    case DW_FORM_ref_udata:
339252723Sdim    case DW_FORM_GNU_str_index:
340252723Sdim    case DW_FORM_GNU_addr_index:
341226584Sdim      debug_info_data.getULEB128(offset_ptr);
342226584Sdim      return true;
343226584Sdim
344226584Sdim    case DW_FORM_indirect:
345226584Sdim      indirect = true;
346226584Sdim      form = debug_info_data.getULEB128(offset_ptr);
347226584Sdim      break;
348245431Sdim
349252723Sdim    // FIXME: 4 for DWARF32, 8 for DWARF64.
350245431Sdim    case DW_FORM_sec_offset:
351252723Sdim      *offset_ptr += 4;
352245431Sdim      return true;
353252723Sdim
354226584Sdim    default:
355226584Sdim      return false;
356226584Sdim    }
357226584Sdim  } while (indirect);
358226584Sdim  return true;
359226584Sdim}
360226584Sdim
361226584Sdimvoid
362263509SdimDWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
363252723Sdim  DataExtractor debug_str_data(cu->getStringSection(), true, 0);
364252723Sdim  DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
365263509Sdim  uint64_t uvalue = Value.uval;
366226584Sdim  bool cu_relative_offset = false;
367226584Sdim
368226584Sdim  switch (Form) {
369235633Sdim  case DW_FORM_addr:      OS << format("0x%016" PRIx64, uvalue); break;
370252723Sdim  case DW_FORM_GNU_addr_index: {
371252723Sdim    OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
372263509Sdim    uint64_t Address;
373263509Sdim    if (cu->getAddrOffsetSectionItem(uvalue, Address))
374263509Sdim      OS << format("0x%016" PRIx64, Address);
375263509Sdim    else
376252723Sdim      OS << "<no .debug_addr section>";
377252723Sdim    break;
378252723Sdim  }
379245431Sdim  case DW_FORM_flag_present: OS << "true"; break;
380226584Sdim  case DW_FORM_flag:
381235633Sdim  case DW_FORM_data1:     OS << format("0x%02x", (uint8_t)uvalue); break;
382235633Sdim  case DW_FORM_data2:     OS << format("0x%04x", (uint16_t)uvalue); break;
383235633Sdim  case DW_FORM_data4:     OS << format("0x%08x", (uint32_t)uvalue); break;
384245431Sdim  case DW_FORM_ref_sig8:
385235633Sdim  case DW_FORM_data8:     OS << format("0x%016" PRIx64, uvalue); break;
386226584Sdim  case DW_FORM_string:
387226584Sdim    OS << '"';
388263509Sdim    OS.write_escaped(Value.cstr);
389226584Sdim    OS << '"';
390226584Sdim    break;
391245431Sdim  case DW_FORM_exprloc:
392226584Sdim  case DW_FORM_block:
393226584Sdim  case DW_FORM_block1:
394226584Sdim  case DW_FORM_block2:
395226584Sdim  case DW_FORM_block4:
396226584Sdim    if (uvalue > 0) {
397226584Sdim      switch (Form) {
398245431Sdim      case DW_FORM_exprloc:
399235633Sdim      case DW_FORM_block:  OS << format("<0x%" PRIx64 "> ", uvalue);     break;
400226584Sdim      case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
401226584Sdim      case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
402226584Sdim      case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
403226584Sdim      default: break;
404226584Sdim      }
405226584Sdim
406226584Sdim      const uint8_t* data_ptr = Value.data;
407226584Sdim      if (data_ptr) {
408226584Sdim        // uvalue contains size of block
409226584Sdim        const uint8_t* end_data_ptr = data_ptr + uvalue;
410226584Sdim        while (data_ptr < end_data_ptr) {
411226584Sdim          OS << format("%2.2x ", *data_ptr);
412226584Sdim          ++data_ptr;
413226584Sdim        }
414226584Sdim      }
415226584Sdim      else
416226584Sdim        OS << "NULL";
417226584Sdim    }
418226584Sdim    break;
419226584Sdim
420263509Sdim  case DW_FORM_sdata:     OS << Value.sval; break;
421263509Sdim  case DW_FORM_udata:     OS << Value.uval; break;
422226584Sdim  case DW_FORM_strp: {
423226584Sdim    OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
424263509Sdim    Optional<const char *> DbgStr = getAsCString(cu);
425263509Sdim    if (DbgStr.hasValue()) {
426226584Sdim      OS << '"';
427263509Sdim      OS.write_escaped(DbgStr.getValue());
428226584Sdim      OS << '"';
429226584Sdim    }
430226584Sdim    break;
431226584Sdim  }
432252723Sdim  case DW_FORM_GNU_str_index: {
433252723Sdim    OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
434263509Sdim    Optional<const char *> DbgStr = getAsCString(cu);
435263509Sdim    if (DbgStr.hasValue()) {
436252723Sdim      OS << '"';
437263509Sdim      OS.write_escaped(DbgStr.getValue());
438252723Sdim      OS << '"';
439252723Sdim    }
440252723Sdim    break;
441252723Sdim  }
442226584Sdim  case DW_FORM_ref_addr:
443235633Sdim    OS << format("0x%016" PRIx64, uvalue);
444226584Sdim    break;
445226584Sdim  case DW_FORM_ref1:
446226584Sdim    cu_relative_offset = true;
447226584Sdim    OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
448226584Sdim    break;
449226584Sdim  case DW_FORM_ref2:
450226584Sdim    cu_relative_offset = true;
451226584Sdim    OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
452226584Sdim    break;
453226584Sdim  case DW_FORM_ref4:
454226584Sdim    cu_relative_offset = true;
455226584Sdim    OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
456226584Sdim    break;
457226584Sdim  case DW_FORM_ref8:
458226584Sdim    cu_relative_offset = true;
459235633Sdim    OS << format("cu + 0x%8.8" PRIx64, uvalue);
460226584Sdim    break;
461226584Sdim  case DW_FORM_ref_udata:
462226584Sdim    cu_relative_offset = true;
463235633Sdim    OS << format("cu + 0x%" PRIx64, uvalue);
464226584Sdim    break;
465226584Sdim
466226584Sdim    // All DW_FORM_indirect attributes should be resolved prior to calling
467226584Sdim    // this function
468226584Sdim  case DW_FORM_indirect:
469226584Sdim    OS << "DW_FORM_indirect";
470226584Sdim    break;
471245431Sdim
472252723Sdim    // Should be formatted to 64-bit for DWARF64.
473245431Sdim  case DW_FORM_sec_offset:
474252723Sdim    OS << format("0x%08x", (uint32_t)uvalue);
475245431Sdim    break;
476252723Sdim
477226584Sdim  default:
478226584Sdim    OS << format("DW_FORM(0x%4.4x)", Form);
479226584Sdim    break;
480226584Sdim  }
481226584Sdim
482226584Sdim  if (cu_relative_offset)
483235633Sdim    OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
484226584Sdim}
485226584Sdim
486263509SdimOptional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
487263509Sdim  if (!isFormClass(FC_String))
488263509Sdim    return None;
489263509Sdim  if (Form == DW_FORM_string)
490226584Sdim    return Value.cstr;
491263509Sdim  if (U == 0)
492263509Sdim    return None;
493263509Sdim  uint32_t Offset = Value.uval;
494263509Sdim  if (Form == DW_FORM_GNU_str_index) {
495263509Sdim    uint32_t StrOffset;
496263509Sdim    if (!U->getStringOffsetSectionItem(Offset, StrOffset))
497263509Sdim      return None;
498263509Sdim    Offset = StrOffset;
499226584Sdim  }
500263509Sdim  if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
501263509Sdim    return Str;
502263509Sdim  }
503263509Sdim  return None;
504226584Sdim}
505226584Sdim
506263509SdimOptional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
507263509Sdim  if (!isFormClass(FC_Address))
508263509Sdim    return None;
509263509Sdim  if (Form == DW_FORM_GNU_addr_index) {
510263509Sdim    uint32_t Index = Value.uval;
511263509Sdim    uint64_t Result;
512263509Sdim    if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result))
513263509Sdim      return None;
514263509Sdim    return Result;
515226584Sdim  }
516263509Sdim  return Value.uval;
517226584Sdim}
518226584Sdim
519263509SdimOptional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
520263509Sdim  if (!isFormClass(FC_Reference))
521263509Sdim    return None;
522226584Sdim  switch (Form) {
523226584Sdim  case DW_FORM_ref1:
524226584Sdim  case DW_FORM_ref2:
525226584Sdim  case DW_FORM_ref4:
526226584Sdim  case DW_FORM_ref8:
527226584Sdim  case DW_FORM_ref_udata:
528263509Sdim    if (U == 0)
529263509Sdim      return None;
530263509Sdim    return Value.uval + U->getOffset();
531263509Sdim  case DW_FORM_ref_addr:
532263509Sdim    return Value.uval;
533263509Sdim  // FIXME: Add proper support for DW_FORM_ref_sig8
534226584Sdim  default:
535263509Sdim    return Value.uval;
536226584Sdim  }
537226584Sdim}
538226584Sdim
539263509SdimOptional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
540263509Sdim  if (!isFormClass(FC_SectionOffset))
541263509Sdim    return None;
542263509Sdim  return Value.uval;
543226584Sdim}
544226584Sdim
545263509SdimOptional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
546263509Sdim  if (!isFormClass(FC_Constant) || Form == DW_FORM_sdata)
547263509Sdim    return None;
548263509Sdim  return Value.uval;
549226584Sdim}
550