~pali/+junk/llvm-toolchain-3.7

« back to all changes in this revision

Viewing changes to lib/DebugInfo/DWARF/DWARFFormValue.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2015-07-15 17:51:08 UTC
  • Revision ID: package-import@ubuntu.com-20150715175108-l8mynwovkx4zx697
Tags: upstream-3.7~+rc2
ImportĀ upstreamĀ versionĀ 3.7~+rc2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>
 
22
using namespace llvm;
 
23
using namespace dwarf;
 
24
using namespace syntax;
 
25
 
 
26
namespace {
 
27
uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
 
28
  // FIXME: Support DWARF64.
 
29
  return (Version == 2) ? AddrSize : 4;
 
30
}
 
31
 
 
32
template <uint8_t AddrSize, uint8_t RefAddrSize>
 
33
ArrayRef<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
 
 
66
ArrayRef<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
 
 
80
static 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
 
 
111
bool 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 more forms from DWARF4 and DWARF5 proposals.
 
117
  switch (Form) {
 
118
  case DW_FORM_ref_sig8:
 
119
  case DW_FORM_GNU_ref_alt:
 
120
    return (FC == FC_Reference);
 
121
  case DW_FORM_GNU_addr_index:
 
122
    return (FC == FC_Address);
 
123
  case DW_FORM_GNU_str_index:
 
124
  case DW_FORM_GNU_strp_alt:
 
125
    return (FC == FC_String);
 
126
  }
 
127
  // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
 
128
  // Don't check for DWARF version here, as some producers may still do this
 
129
  // by mistake.
 
130
  return (Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
 
131
         FC == FC_SectionOffset;
 
132
}
 
133
 
 
134
bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
 
135
                                  const DWARFUnit *cu) {
 
136
  bool indirect = false;
 
137
  bool is_block = false;
 
138
  Value.data = nullptr;
 
139
  // Read the value for the form into value and follow and DW_FORM_indirect
 
140
  // instances we run into
 
141
  do {
 
142
    indirect = false;
 
143
    switch (Form) {
 
144
    case DW_FORM_addr:
 
145
    case DW_FORM_ref_addr: {
 
146
      if (!cu)
 
147
        return false;
 
148
      uint16_t AddrSize =
 
149
          (Form == DW_FORM_addr)
 
150
              ? cu->getAddressByteSize()
 
151
              : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
 
152
      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
 
153
      if (AI != cu->getRelocMap()->end()) {
 
154
        const std::pair<uint8_t, int64_t> &R = AI->second;
 
155
        Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
 
156
      } else
 
157
        Value.uval = data.getUnsigned(offset_ptr, AddrSize);
 
158
      break;
 
159
    }
 
160
    case DW_FORM_exprloc:
 
161
    case DW_FORM_block:
 
162
      Value.uval = data.getULEB128(offset_ptr);
 
163
      is_block = true;
 
164
      break;
 
165
    case DW_FORM_block1:
 
166
      Value.uval = data.getU8(offset_ptr);
 
167
      is_block = true;
 
168
      break;
 
169
    case DW_FORM_block2:
 
170
      Value.uval = data.getU16(offset_ptr);
 
171
      is_block = true;
 
172
      break;
 
173
    case DW_FORM_block4:
 
174
      Value.uval = data.getU32(offset_ptr);
 
175
      is_block = true;
 
176
      break;
 
177
    case DW_FORM_data1:
 
178
    case DW_FORM_ref1:
 
179
    case DW_FORM_flag:
 
180
      Value.uval = data.getU8(offset_ptr);
 
181
      break;
 
182
    case DW_FORM_data2:
 
183
    case DW_FORM_ref2:
 
184
      Value.uval = data.getU16(offset_ptr);
 
185
      break;
 
186
    case DW_FORM_data4:
 
187
    case DW_FORM_ref4: {
 
188
      Value.uval = data.getU32(offset_ptr);
 
189
      if (!cu)
 
190
        break;
 
191
      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4);
 
192
      if (AI != cu->getRelocMap()->end())
 
193
        Value.uval += AI->second.second;
 
194
      break;
 
195
    }
 
196
    case DW_FORM_data8:
 
197
    case DW_FORM_ref8:
 
198
      Value.uval = data.getU64(offset_ptr);
 
199
      break;
 
200
    case DW_FORM_sdata:
 
201
      Value.sval = data.getSLEB128(offset_ptr);
 
202
      break;
 
203
    case DW_FORM_udata:
 
204
    case DW_FORM_ref_udata:
 
205
      Value.uval = data.getULEB128(offset_ptr);
 
206
      break;
 
207
    case DW_FORM_string:
 
208
      Value.cstr = data.getCStr(offset_ptr);
 
209
      break;
 
210
    case DW_FORM_indirect:
 
211
      Form = data.getULEB128(offset_ptr);
 
212
      indirect = true;
 
213
      break;
 
214
    case DW_FORM_sec_offset:
 
215
    case DW_FORM_strp:
 
216
    case DW_FORM_GNU_ref_alt:
 
217
    case DW_FORM_GNU_strp_alt: {
 
218
      // FIXME: This is 64-bit for DWARF64.
 
219
      Value.uval = data.getU32(offset_ptr);
 
220
      if (!cu)
 
221
        break;
 
222
      RelocAddrMap::const_iterator AI =
 
223
          cu->getRelocMap()->find(*offset_ptr - 4);
 
224
      if (AI != cu->getRelocMap()->end())
 
225
        Value.uval += AI->second.second;
 
226
      break;
 
227
    }
 
228
    case DW_FORM_flag_present:
 
229
      Value.uval = 1;
 
230
      break;
 
231
    case DW_FORM_ref_sig8:
 
232
      Value.uval = data.getU64(offset_ptr);
 
233
      break;
 
234
    case DW_FORM_GNU_addr_index:
 
235
    case DW_FORM_GNU_str_index:
 
236
      Value.uval = data.getULEB128(offset_ptr);
 
237
      break;
 
238
    default:
 
239
      return false;
 
240
    }
 
241
  } while (indirect);
 
242
 
 
243
  if (is_block) {
 
244
    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
 
245
    Value.data = nullptr;
 
246
    if (!str.empty()) {
 
247
      Value.data = reinterpret_cast<const uint8_t *>(str.data());
 
248
      *offset_ptr += Value.uval;
 
249
    }
 
250
  }
 
251
 
 
252
  return true;
 
253
}
 
254
 
 
255
bool
 
256
DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
 
257
                          const DWARFUnit *cu) const {
 
258
  return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
 
259
}
 
260
 
 
261
bool
 
262
DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
 
263
                          uint32_t *offset_ptr, const DWARFUnit *cu) {
 
264
  bool indirect = false;
 
265
  do {
 
266
    switch (form) {
 
267
    // Blocks if inlined data that have a length field and the data bytes
 
268
    // inlined in the .debug_info
 
269
    case DW_FORM_exprloc:
 
270
    case DW_FORM_block: {
 
271
      uint64_t size = debug_info_data.getULEB128(offset_ptr);
 
272
      *offset_ptr += size;
 
273
      return true;
 
274
    }
 
275
    case DW_FORM_block1: {
 
276
      uint8_t size = debug_info_data.getU8(offset_ptr);
 
277
      *offset_ptr += size;
 
278
      return true;
 
279
    }
 
280
    case DW_FORM_block2: {
 
281
      uint16_t size = debug_info_data.getU16(offset_ptr);
 
282
      *offset_ptr += size;
 
283
      return true;
 
284
    }
 
285
    case DW_FORM_block4: {
 
286
      uint32_t size = debug_info_data.getU32(offset_ptr);
 
287
      *offset_ptr += size;
 
288
      return true;
 
289
    }
 
290
 
 
291
    // Inlined NULL terminated C-strings
 
292
    case DW_FORM_string:
 
293
      debug_info_data.getCStr(offset_ptr);
 
294
      return true;
 
295
 
 
296
    // Compile unit address sized values
 
297
    case DW_FORM_addr:
 
298
      *offset_ptr += cu->getAddressByteSize();
 
299
      return true;
 
300
    case DW_FORM_ref_addr:
 
301
      *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
 
302
      return true;
 
303
 
 
304
    // 0 byte values - implied from the form.
 
305
    case DW_FORM_flag_present:
 
306
      return true;
 
307
 
 
308
    // 1 byte values
 
309
    case DW_FORM_data1:
 
310
    case DW_FORM_flag:
 
311
    case DW_FORM_ref1:
 
312
      *offset_ptr += 1;
 
313
      return true;
 
314
 
 
315
    // 2 byte values
 
316
    case DW_FORM_data2:
 
317
    case DW_FORM_ref2:
 
318
      *offset_ptr += 2;
 
319
      return true;
 
320
 
 
321
    // 4 byte values
 
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
    case DW_FORM_strp:
 
352
    case DW_FORM_GNU_ref_alt:
 
353
    case DW_FORM_GNU_strp_alt:
 
354
      *offset_ptr += 4;
 
355
      return true;
 
356
 
 
357
    default:
 
358
      return false;
 
359
    }
 
360
  } while (indirect);
 
361
  return true;
 
362
}
 
363
 
 
364
void
 
365
DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
 
366
  uint64_t uvalue = Value.uval;
 
367
  bool cu_relative_offset = false;
 
368
 
 
369
  switch (Form) {
 
370
  case DW_FORM_addr:      OS << format("0x%016" PRIx64, uvalue); break;
 
371
  case DW_FORM_GNU_addr_index: {
 
372
    OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
 
373
    uint64_t Address;
 
374
    if (cu->getAddrOffsetSectionItem(uvalue, Address))
 
375
      OS << format("0x%016" PRIx64, Address);
 
376
    else
 
377
      OS << "<no .debug_addr section>";
 
378
    break;
 
379
  }
 
380
  case DW_FORM_flag_present: OS << "true"; break;
 
381
  case DW_FORM_flag:
 
382
  case DW_FORM_data1:     OS << format("0x%02x", (uint8_t)uvalue); break;
 
383
  case DW_FORM_data2:     OS << format("0x%04x", (uint16_t)uvalue); break;
 
384
  case DW_FORM_data4:     OS << format("0x%08x", (uint32_t)uvalue); break;
 
385
  case DW_FORM_ref_sig8:
 
386
  case DW_FORM_data8:     OS << format("0x%016" PRIx64, uvalue); break;
 
387
  case DW_FORM_string:
 
388
    OS << '"';
 
389
    OS.write_escaped(Value.cstr);
 
390
    OS << '"';
 
391
    break;
 
392
  case DW_FORM_exprloc:
 
393
  case DW_FORM_block:
 
394
  case DW_FORM_block1:
 
395
  case DW_FORM_block2:
 
396
  case DW_FORM_block4:
 
397
    if (uvalue > 0) {
 
398
      switch (Form) {
 
399
      case DW_FORM_exprloc:
 
400
      case DW_FORM_block:  OS << format("<0x%" PRIx64 "> ", uvalue);     break;
 
401
      case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
 
402
      case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
 
403
      case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
 
404
      default: break;
 
405
      }
 
406
 
 
407
      const uint8_t* data_ptr = Value.data;
 
408
      if (data_ptr) {
 
409
        // uvalue contains size of block
 
410
        const uint8_t* end_data_ptr = data_ptr + uvalue;
 
411
        while (data_ptr < end_data_ptr) {
 
412
          OS << format("%2.2x ", *data_ptr);
 
413
          ++data_ptr;
 
414
        }
 
415
      }
 
416
      else
 
417
        OS << "NULL";
 
418
    }
 
419
    break;
 
420
 
 
421
  case DW_FORM_sdata:     OS << Value.sval; break;
 
422
  case DW_FORM_udata:     OS << Value.uval; break;
 
423
  case DW_FORM_strp: {
 
424
    OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
 
425
    dumpString(OS, cu);
 
426
    break;
 
427
  }
 
428
  case DW_FORM_GNU_str_index: {
 
429
    OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
 
430
    dumpString(OS, cu);
 
431
    break;
 
432
  }
 
433
  case DW_FORM_GNU_strp_alt: {
 
434
    OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue);
 
435
    dumpString(OS, cu);
 
436
    break;
 
437
  }
 
438
  case DW_FORM_ref_addr:
 
439
    OS << format("0x%016" PRIx64, uvalue);
 
440
    break;
 
441
  case DW_FORM_ref1:
 
442
    cu_relative_offset = true;
 
443
    OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
 
444
    break;
 
445
  case DW_FORM_ref2:
 
446
    cu_relative_offset = true;
 
447
    OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
 
448
    break;
 
449
  case DW_FORM_ref4:
 
450
    cu_relative_offset = true;
 
451
    OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
 
452
    break;
 
453
  case DW_FORM_ref8:
 
454
    cu_relative_offset = true;
 
455
    OS << format("cu + 0x%8.8" PRIx64, uvalue);
 
456
    break;
 
457
  case DW_FORM_ref_udata:
 
458
    cu_relative_offset = true;
 
459
    OS << format("cu + 0x%" PRIx64, uvalue);
 
460
    break;
 
461
  case DW_FORM_GNU_ref_alt:
 
462
    OS << format("<alt 0x%" PRIx64 ">", uvalue);
 
463
    break;
 
464
 
 
465
    // All DW_FORM_indirect attributes should be resolved prior to calling
 
466
    // this function
 
467
  case DW_FORM_indirect:
 
468
    OS << "DW_FORM_indirect";
 
469
    break;
 
470
 
 
471
    // Should be formatted to 64-bit for DWARF64.
 
472
  case DW_FORM_sec_offset:
 
473
    OS << format("0x%08x", (uint32_t)uvalue);
 
474
    break;
 
475
 
 
476
  default:
 
477
    OS << format("DW_FORM(0x%4.4x)", Form);
 
478
    break;
 
479
  }
 
480
 
 
481
  if (cu_relative_offset) {
 
482
    OS << " => {";
 
483
    WithColor(OS, syntax::Address).get()
 
484
      << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0));
 
485
    OS << "}";
 
486
  }
 
487
}
 
488
 
 
489
void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const {
 
490
  Optional<const char *> DbgStr = getAsCString(U);
 
491
  if (DbgStr.hasValue()) {
 
492
    raw_ostream &COS = WithColor(OS, syntax::String);
 
493
    COS << '"';
 
494
    COS.write_escaped(DbgStr.getValue());
 
495
    COS << '"';
 
496
  }
 
497
}
 
498
 
 
499
Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
 
500
  if (!isFormClass(FC_String))
 
501
    return None;
 
502
  if (Form == DW_FORM_string)
 
503
    return Value.cstr;
 
504
  // FIXME: Add support for DW_FORM_GNU_strp_alt
 
505
  if (Form == DW_FORM_GNU_strp_alt || U == nullptr)
 
506
    return None;
 
507
  uint32_t Offset = Value.uval;
 
508
  if (Form == DW_FORM_GNU_str_index) {
 
509
    uint32_t StrOffset;
 
510
    if (!U->getStringOffsetSectionItem(Offset, StrOffset))
 
511
      return None;
 
512
    Offset = StrOffset;
 
513
  }
 
514
  if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
 
515
    return Str;
 
516
  }
 
517
  return None;
 
518
}
 
519
 
 
520
Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
 
521
  if (!isFormClass(FC_Address))
 
522
    return None;
 
523
  if (Form == DW_FORM_GNU_addr_index) {
 
524
    uint32_t Index = Value.uval;
 
525
    uint64_t Result;
 
526
    if (!U || !U->getAddrOffsetSectionItem(Index, Result))
 
527
      return None;
 
528
    return Result;
 
529
  }
 
530
  return Value.uval;
 
531
}
 
532
 
 
533
Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
 
534
  if (!isFormClass(FC_Reference))
 
535
    return None;
 
536
  switch (Form) {
 
537
  case DW_FORM_ref1:
 
538
  case DW_FORM_ref2:
 
539
  case DW_FORM_ref4:
 
540
  case DW_FORM_ref8:
 
541
  case DW_FORM_ref_udata:
 
542
    if (!U)
 
543
      return None;
 
544
    return Value.uval + U->getOffset();
 
545
  case DW_FORM_ref_addr:
 
546
    return Value.uval;
 
547
  // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt.
 
548
  default:
 
549
    return None;
 
550
  }
 
551
}
 
552
 
 
553
Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
 
554
  if (!isFormClass(FC_SectionOffset))
 
555
    return None;
 
556
  return Value.uval;
 
557
}
 
558
 
 
559
Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
 
560
  if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag))
 
561
      || Form == DW_FORM_sdata)
 
562
    return None;
 
563
  return Value.uval;
 
564
}
 
565
 
 
566
Optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
 
567
  if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
 
568
      (Form == DW_FORM_udata && uint64_t(LLONG_MAX) < Value.uval))
 
569
    return None;
 
570
  switch (Form) {
 
571
  case DW_FORM_data4:
 
572
    return int32_t(Value.uval);
 
573
  case DW_FORM_data2:
 
574
    return int16_t(Value.uval);
 
575
  case DW_FORM_data1:
 
576
    return int8_t(Value.uval);
 
577
  case DW_FORM_sdata:
 
578
  case DW_FORM_data8:
 
579
  default:
 
580
    return Value.sval;
 
581
  }
 
582
}
 
583
 
 
584
Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {
 
585
  if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc))
 
586
    return None;
 
587
  return ArrayRef<uint8_t>(Value.data, Value.uval);
 
588
}
 
589