• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "DWARFFormValue.h"
11 #include "DWARFCompileUnit.h"
12 #include "DWARFContext.h"
13 #include "llvm/Support/Dwarf.h"
14 #include "llvm/Support/Format.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include <cassert>
17 using namespace llvm;
18 using namespace dwarf;
19 
20 static const uint8_t form_sizes_addr4[] = {
21   0, // 0x00 unused
22   4, // 0x01 DW_FORM_addr
23   0, // 0x02 unused
24   0, // 0x03 DW_FORM_block2
25   0, // 0x04 DW_FORM_block4
26   2, // 0x05 DW_FORM_data2
27   4, // 0x06 DW_FORM_data4
28   8, // 0x07 DW_FORM_data8
29   0, // 0x08 DW_FORM_string
30   0, // 0x09 DW_FORM_block
31   0, // 0x0a DW_FORM_block1
32   1, // 0x0b DW_FORM_data1
33   1, // 0x0c DW_FORM_flag
34   0, // 0x0d DW_FORM_sdata
35   4, // 0x0e DW_FORM_strp
36   0, // 0x0f DW_FORM_udata
37   4, // 0x10 DW_FORM_ref_addr
38   1, // 0x11 DW_FORM_ref1
39   2, // 0x12 DW_FORM_ref2
40   4, // 0x13 DW_FORM_ref4
41   8, // 0x14 DW_FORM_ref8
42   0, // 0x15 DW_FORM_ref_udata
43   0, // 0x16 DW_FORM_indirect
44 };
45 
46 static const uint8_t form_sizes_addr8[] = {
47   0, // 0x00 unused
48   8, // 0x01 DW_FORM_addr
49   0, // 0x02 unused
50   0, // 0x03 DW_FORM_block2
51   0, // 0x04 DW_FORM_block4
52   2, // 0x05 DW_FORM_data2
53   4, // 0x06 DW_FORM_data4
54   8, // 0x07 DW_FORM_data8
55   0, // 0x08 DW_FORM_string
56   0, // 0x09 DW_FORM_block
57   0, // 0x0a DW_FORM_block1
58   1, // 0x0b DW_FORM_data1
59   1, // 0x0c DW_FORM_flag
60   0, // 0x0d DW_FORM_sdata
61   4, // 0x0e DW_FORM_strp
62   0, // 0x0f DW_FORM_udata
63   8, // 0x10 DW_FORM_ref_addr
64   1, // 0x11 DW_FORM_ref1
65   2, // 0x12 DW_FORM_ref2
66   4, // 0x13 DW_FORM_ref4
67   8, // 0x14 DW_FORM_ref8
68   0, // 0x15 DW_FORM_ref_udata
69   0, // 0x16 DW_FORM_indirect
70 };
71 
72 const uint8_t *
getFixedFormSizesForAddressSize(uint8_t addr_size)73 DWARFFormValue::getFixedFormSizesForAddressSize(uint8_t addr_size) {
74   switch (addr_size) {
75   case 4: return form_sizes_addr4;
76   case 8: return form_sizes_addr8;
77   }
78   return NULL;
79 }
80 
81 bool
extractValue(DataExtractor data,uint32_t * offset_ptr,const DWARFCompileUnit * cu)82 DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
83                              const DWARFCompileUnit *cu) {
84   bool indirect = false;
85   bool is_block = false;
86   Value.data = NULL;
87   // Read the value for the form into value and follow and DW_FORM_indirect
88   // instances we run into
89   do {
90     indirect = false;
91     switch (Form) {
92     case DW_FORM_addr:
93     case DW_FORM_ref_addr:
94       Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
95       break;
96     case DW_FORM_block:
97       Value.uval = data.getULEB128(offset_ptr);
98       is_block = true;
99       break;
100     case DW_FORM_block1:
101       Value.uval = data.getU8(offset_ptr);
102       is_block = true;
103       break;
104     case DW_FORM_block2:
105       Value.uval = data.getU16(offset_ptr);
106       is_block = true;
107       break;
108     case DW_FORM_block4:
109       Value.uval = data.getU32(offset_ptr);
110       is_block = true;
111       break;
112     case DW_FORM_data1:
113     case DW_FORM_ref1:
114     case DW_FORM_flag:
115       Value.uval = data.getU8(offset_ptr);
116       break;
117     case DW_FORM_data2:
118     case DW_FORM_ref2:
119       Value.uval = data.getU16(offset_ptr);
120       break;
121     case DW_FORM_data4:
122     case DW_FORM_ref4:
123       Value.uval = data.getU32(offset_ptr);
124       break;
125     case DW_FORM_data8:
126     case DW_FORM_ref8:
127       Value.uval = data.getU64(offset_ptr);
128       break;
129     case DW_FORM_sdata:
130       Value.sval = data.getSLEB128(offset_ptr);
131       break;
132     case DW_FORM_strp:
133       Value.uval = data.getU32(offset_ptr);
134       break;
135     case DW_FORM_udata:
136     case DW_FORM_ref_udata:
137       Value.uval = data.getULEB128(offset_ptr);
138       break;
139     case DW_FORM_string:
140       Value.cstr = data.getCStr(offset_ptr);
141       // Set the string value to also be the data for inlined cstr form
142       // values only so we can tell the differnence between DW_FORM_string
143       // and DW_FORM_strp form values
144       Value.data = (uint8_t*)Value.cstr;
145       break;
146     case DW_FORM_indirect:
147       Form = data.getULEB128(offset_ptr);
148       indirect = true;
149       break;
150     default:
151       return false;
152     }
153   } while (indirect);
154 
155   if (is_block) {
156     StringRef str = data.getData().substr(*offset_ptr, Value.uval);
157     Value.data = NULL;
158     if (!str.empty()) {
159       Value.data = reinterpret_cast<const uint8_t *>(str.data());
160       *offset_ptr += Value.uval;
161     }
162   }
163 
164   return true;
165 }
166 
167 bool
skipValue(DataExtractor debug_info_data,uint32_t * offset_ptr,const DWARFCompileUnit * cu) const168 DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
169                           const DWARFCompileUnit *cu) const {
170   return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
171 }
172 
173 bool
skipValue(uint16_t form,DataExtractor debug_info_data,uint32_t * offset_ptr,const DWARFCompileUnit * cu)174 DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
175                           uint32_t *offset_ptr, const DWARFCompileUnit *cu) {
176   bool indirect = false;
177   do {
178     indirect = false;
179     switch (form) {
180     // Blocks if inlined data that have a length field and the data bytes
181     // inlined in the .debug_info
182     case DW_FORM_block: {
183       uint64_t size = debug_info_data.getULEB128(offset_ptr);
184       *offset_ptr += size;
185       return true;
186     }
187     case DW_FORM_block1: {
188       uint8_t size = debug_info_data.getU8(offset_ptr);
189       *offset_ptr += size;
190       return true;
191     }
192     case DW_FORM_block2: {
193       uint16_t size = debug_info_data.getU16(offset_ptr);
194       *offset_ptr += size;
195       return true;
196     }
197     case DW_FORM_block4: {
198       uint32_t size = debug_info_data.getU32(offset_ptr);
199       *offset_ptr += size;
200       return true;
201     }
202 
203     // Inlined NULL terminated C-strings
204     case DW_FORM_string:
205       debug_info_data.getCStr(offset_ptr);
206       return true;
207 
208     // Compile unit address sized values
209     case DW_FORM_addr:
210     case DW_FORM_ref_addr:
211       *offset_ptr += cu->getAddressByteSize();
212       return true;
213 
214     // 1 byte values
215     case DW_FORM_data1:
216     case DW_FORM_flag:
217     case DW_FORM_ref1:
218       *offset_ptr += 1;
219       return true;
220 
221     // 2 byte values
222     case DW_FORM_data2:
223     case DW_FORM_ref2:
224       *offset_ptr += 2;
225       return true;
226 
227     // 4 byte values
228     case DW_FORM_strp:
229     case DW_FORM_data4:
230     case DW_FORM_ref4:
231       *offset_ptr += 4;
232       return true;
233 
234     // 8 byte values
235     case DW_FORM_data8:
236     case DW_FORM_ref8:
237       *offset_ptr += 8;
238       return true;
239 
240     // signed or unsigned LEB 128 values
241     //  case DW_FORM_APPLE_db_str:
242     case DW_FORM_sdata:
243     case DW_FORM_udata:
244     case DW_FORM_ref_udata:
245       debug_info_data.getULEB128(offset_ptr);
246       return true;
247 
248     case DW_FORM_indirect:
249       indirect = true;
250       form = debug_info_data.getULEB128(offset_ptr);
251       break;
252     default:
253       return false;
254     }
255   } while (indirect);
256   return true;
257 }
258 
259 void
dump(raw_ostream & OS,const DWARFCompileUnit * cu) const260 DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
261   DataExtractor debug_str_data(cu->getContext().getStringSection(), true, 0);
262   uint64_t uvalue = getUnsigned();
263   bool cu_relative_offset = false;
264 
265   switch (Form) {
266   case DW_FORM_addr:      OS << format("0x%016x", uvalue); break;
267   case DW_FORM_flag:
268   case DW_FORM_data1:     OS << format("0x%02x", uvalue);  break;
269   case DW_FORM_data2:     OS << format("0x%04x", uvalue);  break;
270   case DW_FORM_data4:     OS << format("0x%08x", uvalue);  break;
271   case DW_FORM_data8:     OS << format("0x%016x", uvalue); break;
272   case DW_FORM_string:
273     OS << '"';
274     OS.write_escaped(getAsCString(NULL));
275     OS << '"';
276     break;
277   case DW_FORM_block:
278   case DW_FORM_block1:
279   case DW_FORM_block2:
280   case DW_FORM_block4:
281     if (uvalue > 0) {
282       switch (Form) {
283       case DW_FORM_block:  OS << format("<0x%llx> ", uvalue);            break;
284       case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
285       case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
286       case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
287       default: break;
288       }
289 
290       const uint8_t* data_ptr = Value.data;
291       if (data_ptr) {
292         // uvalue contains size of block
293         const uint8_t* end_data_ptr = data_ptr + uvalue;
294         while (data_ptr < end_data_ptr) {
295           OS << format("%2.2x ", *data_ptr);
296           ++data_ptr;
297         }
298       }
299       else
300         OS << "NULL";
301     }
302     break;
303 
304   case DW_FORM_sdata:     OS << getSigned();   break;
305   case DW_FORM_udata:     OS << getUnsigned(); break;
306   case DW_FORM_strp: {
307     OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
308     const char* dbg_str = getAsCString(&debug_str_data);
309     if (dbg_str) {
310       OS << '"';
311       OS.write_escaped(dbg_str);
312       OS << '"';
313     }
314     break;
315   }
316   case DW_FORM_ref_addr:
317     OS << format("0x%016x", uvalue);
318     break;
319   case DW_FORM_ref1:
320     cu_relative_offset = true;
321     OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
322     break;
323   case DW_FORM_ref2:
324     cu_relative_offset = true;
325     OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
326     break;
327   case DW_FORM_ref4:
328     cu_relative_offset = true;
329     OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
330     break;
331   case DW_FORM_ref8:
332     cu_relative_offset = true;
333     OS << format("cu + 0x%8.8llx", uvalue);
334     break;
335   case DW_FORM_ref_udata:
336     cu_relative_offset = true;
337     OS << format("cu + 0x%llx", uvalue);
338     break;
339 
340     // All DW_FORM_indirect attributes should be resolved prior to calling
341     // this function
342   case DW_FORM_indirect:
343     OS << "DW_FORM_indirect";
344     break;
345   default:
346     OS << format("DW_FORM(0x%4.4x)", Form);
347     break;
348   }
349 
350   if (cu_relative_offset)
351     OS << format(" => {0x%8.8x}", (uvalue + (cu ? cu->getOffset() : 0)));
352 }
353 
354 const char*
getAsCString(const DataExtractor * debug_str_data_ptr) const355 DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const {
356   if (isInlinedCStr()) {
357     return Value.cstr;
358   } else if (debug_str_data_ptr) {
359     uint32_t offset = Value.uval;
360     return debug_str_data_ptr->getCStr(&offset);
361   }
362   return NULL;
363 }
364 
getReference(const DWARFCompileUnit * cu) const365 uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
366   uint64_t die_offset = Value.uval;
367   switch (Form) {
368   case DW_FORM_ref1:
369   case DW_FORM_ref2:
370   case DW_FORM_ref4:
371   case DW_FORM_ref8:
372   case DW_FORM_ref_udata:
373       die_offset += (cu ? cu->getOffset() : 0);
374       break;
375   default:
376       break;
377   }
378 
379   return die_offset;
380 }
381 
382 bool
resolveCompileUnitReferences(const DWARFCompileUnit * cu)383 DWARFFormValue::resolveCompileUnitReferences(const DWARFCompileUnit *cu) {
384   switch (Form) {
385   case DW_FORM_ref1:
386   case DW_FORM_ref2:
387   case DW_FORM_ref4:
388   case DW_FORM_ref8:
389   case DW_FORM_ref_udata:
390     Value.uval += cu->getOffset();
391     Form = DW_FORM_ref_addr;
392     return true;
393   default:
394     break;
395   }
396   return false;
397 }
398 
BlockData() const399 const uint8_t *DWARFFormValue::BlockData() const {
400   if (!isInlinedCStr())
401     return Value.data;
402   return NULL;
403 }
404 
isBlockForm(uint16_t form)405 bool DWARFFormValue::isBlockForm(uint16_t form) {
406   switch (form) {
407   case DW_FORM_block:
408   case DW_FORM_block1:
409   case DW_FORM_block2:
410   case DW_FORM_block4:
411     return true;
412   }
413   return false;
414 }
415 
isDataForm(uint16_t form)416 bool DWARFFormValue::isDataForm(uint16_t form) {
417   switch (form) {
418   case DW_FORM_sdata:
419   case DW_FORM_udata:
420   case DW_FORM_data1:
421   case DW_FORM_data2:
422   case DW_FORM_data4:
423   case DW_FORM_data8:
424     return true;
425   }
426   return false;
427 }
428