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