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