llvm.org GIT mirror llvm / c525323
DebugInfo: Introduce the notion of "form classes" Summary: Use DWARF4 table of form classes to fetch attributes from DIE in a more consistent way. This shouldn't change the functionality and serves as a refactoring for upcoming change: DW_AT_high_pc has different semantics depending on its form class. Reviewers: dblaikie, echristo Reviewed By: echristo CC: echristo, llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1961 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193553 91177308-0d34-0410-b5e6-96231b3b80d8 Alexey Samsonov 7 years ago
7 changed file(s) with 208 addition(s) and 81 deletion(s). Raw diff Collapse all Expand all
99 #ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
1010 #define LLVM_DEBUGINFO_DWARFFORMVALUE_H
1111
12 #include "llvm/ADT/Optional.h"
1213 #include "llvm/Support/DataExtractor.h"
1314
1415 namespace llvm {
1718 class raw_ostream;
1819
1920 class DWARFFormValue {
21 public:
22 enum FormClass {
23 FC_Unknown,
24 FC_Address,
25 FC_Block,
26 FC_Constant,
27 FC_String,
28 FC_Flag,
29 FC_Reference,
30 FC_Indirect,
31 FC_SectionOffset,
32 FC_Exprloc
33 };
34
35 private:
2036 struct ValueType {
2137 ValueType() : data(NULL) {
2238 uval = 0;
3450 ValueType Value; // Contains all data for the form.
3551
3652 public:
37 DWARFFormValue(uint16_t form = 0) : Form(form) {}
53 DWARFFormValue(uint16_t Form = 0) : Form(Form) {}
3854 uint16_t getForm() const { return Form; }
39 const ValueType& value() const { return Value; }
55 bool isFormClass(FormClass FC) const;
56
4057 void dump(raw_ostream &OS, const DWARFUnit *U) const;
4158 bool extractValue(DataExtractor data, uint32_t *offset_ptr,
4259 const DWARFUnit *u);
4461 return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr;
4562 }
4663
47 uint64_t getReference(const DWARFUnit *U) const;
48 uint64_t getUnsigned() const { return Value.uval; }
49 int64_t getSigned() const { return Value.sval; }
50 const char *getAsCString(const DWARFUnit *U) const;
51 uint64_t getAsAddress(const DWARFUnit *U) const;
64 /// getAsFoo functions below return the extracted value as Foo if only
65 /// DWARFFormValue has form class is suitable for representing Foo.
66 Optional getAsReference(const DWARFUnit *U) const;
67 Optional getAsUnsignedConstant() const;
68 Optional getAsCString(const DWARFUnit *U) const;
69 Optional getAsAddress(const DWARFUnit *U) const;
70 Optional getAsSectionOffset() const;
5271
5372 bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
5473 const DWARFUnit *u) const;
101101 DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
102102 savedAddressByteSize = cu->getAddressByteSize();
103103 unsigned stmtOffset =
104 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
105 -1U);
104 cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
105 cu, DW_AT_stmt_list, -1U);
106106 if (stmtOffset != -1U) {
107107 DataExtractor lineData(getLineSection().Data, isLittleEndian(),
108108 savedAddressByteSize);
261261 Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
262262
263263 unsigned stmtOffset =
264 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
265 -1U);
264 cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
265 cu, DW_AT_stmt_list, -1U);
266266 if (stmtOffset == -1U)
267267 return 0; // No line table for this compile unit.
268268
159159 ((Attr == DW_AT_entry_pc) || (Attr == DW_AT_low_pc))) {
160160 DWARFFormValue FormValue(Form);
161161 if (FormValue.extractValue(DebugInfoData, OffsetPtr, U)) {
162 if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc)
163 const_cast(U)->setBaseAddress(FormValue.getUnsigned());
162 if (Attr == DW_AT_low_pc || Attr == DW_AT_entry_pc) {
163 Optional BaseAddr = FormValue.getAsAddress(U);
164 if (BaseAddr.hasValue())
165 const_cast(U)->setBaseAddress(BaseAddr.getValue());
166 }
164167 }
165168 } else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
166169 // Restore the original offset.
209212 const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
210213 const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
211214 DWARFFormValue FormValue;
212 if (getAttributeValue(U, Attr, FormValue))
213 return FormValue.getAsCString(U);
214 return FailValue;
215 if (!getAttributeValue(U, Attr, FormValue))
216 return FailValue;
217 Optional Result = FormValue.getAsCString(U);
218 return Result.hasValue() ? Result.getValue() : FailValue;
215219 }
216220
217221 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
218222 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
219223 DWARFFormValue FormValue;
220 if (getAttributeValue(U, Attr, FormValue))
221 return FormValue.getAsAddress(U);
222 return FailValue;
223 }
224
225 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned(
224 if (!getAttributeValue(U, Attr, FormValue))
225 return FailValue;
226 Optional Result = FormValue.getAsAddress(U);
227 return Result.hasValue() ? Result.getValue() : FailValue;
228 }
229
230 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant(
226231 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
227232 DWARFFormValue FormValue;
228 if (getAttributeValue(U, Attr, FormValue))
229 return FormValue.getUnsigned();
230 return FailValue;
233 if (!getAttributeValue(U, Attr, FormValue))
234 return FailValue;
235 Optional Result = FormValue.getAsUnsignedConstant();
236 return Result.hasValue() ? Result.getValue() : FailValue;
231237 }
232238
233239 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
234240 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
235241 DWARFFormValue FormValue;
236 if (getAttributeValue(U, Attr, FormValue))
237 return FormValue.getReference(U);
238 return FailValue;
242 if (!getAttributeValue(U, Attr, FormValue))
243 return FailValue;
244 Optional Result = FormValue.getAsReference(U);
245 return Result.hasValue() ? Result.getValue() : FailValue;
246 }
247
248 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset(
249 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
250 DWARFFormValue FormValue;
251 if (!getAttributeValue(U, Attr, FormValue))
252 return FailValue;
253 Optional Result = FormValue.getAsSectionOffset();
254 return Result.hasValue() ? Result.getValue() : FailValue;
239255 }
240256
241257 bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
276292 if (getLowAndHighPC(U, LowPC, HighPC))
277293 return (LowPC <= Address && Address <= HighPC);
278294 // Try to get address ranges from .debug_ranges section.
279 uint32_t RangesOffset = getAttributeValueAsReference(U, DW_AT_ranges, -1U);
295 uint32_t RangesOffset =
296 getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
280297 if (RangesOffset != -1U) {
281298 DWARFDebugRangeList RangeList;
282299 if (U->extractRangeList(RangesOffset, RangeList))
324341 uint32_t &CallFile,
325342 uint32_t &CallLine,
326343 uint32_t &CallColumn) const {
327 CallFile = getAttributeValueAsUnsigned(U, DW_AT_call_file, 0);
328 CallLine = getAttributeValueAsUnsigned(U, DW_AT_call_line, 0);
329 CallColumn = getAttributeValueAsUnsigned(U, DW_AT_call_column, 0);
344 CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0);
345 CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0);
346 CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0);
330347 }
331348
332349 DWARFDebugInfoEntryInlinedChain
128128 uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr,
129129 uint64_t FailValue) const;
130130
131 uint64_t getAttributeValueAsUnsigned(const DWARFUnit *U, const uint16_t Attr,
132 uint64_t FailValue) const;
131 uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U,
132 const uint16_t Attr,
133 uint64_t FailValue) const;
133134
134135 uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr,
135136 uint64_t FailValue) const;
137
138 uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U,
139 const uint16_t Attr,
140 uint64_t FailValue) const;
136141
137142 /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
138143 /// Returns true if both attributes are present.
99 #include "llvm/DebugInfo/DWARFFormValue.h"
1010 #include "DWARFCompileUnit.h"
1111 #include "DWARFContext.h"
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/StringRef.h"
1214 #include "llvm/Support/Debug.h"
1315 #include "llvm/Support/Dwarf.h"
1416 #include "llvm/Support/Format.h"
7375 return 0;
7476 }
7577
78 static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
79 DWARFFormValue::FC_Unknown, // 0x0
80 DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr
81 DWARFFormValue::FC_Unknown, // 0x02 unused
82 DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2
83 DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4
84 DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2
85 // --- These can be FC_SectionOffset in DWARF3 and below:
86 DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4
87 DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8
88 // ---
89 DWARFFormValue::FC_String, // 0x08 DW_FORM_string
90 DWARFFormValue::FC_Block, // 0x09 DW_FORM_block
91 DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1
92 DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1
93 DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag
94 DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata
95 DWARFFormValue::FC_String, // 0x0e DW_FORM_strp
96 DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata
97 DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr
98 DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1
99 DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2
100 DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4
101 DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8
102 DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata
103 DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect
104 DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
105 DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc
106 DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present
107 DWARFFormValue::FC_Reference, // 0x20 DW_FORM_ref_sig8
108 };
109
110 bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
111 // First, check DWARF4 form classes.
112 if (Form < ArrayRef(DWARF4FormClasses).size() &&
113 DWARF4FormClasses[Form] == FC)
114 return true;
115 // Check for some DWARF5 forms.
116 if (Form == DW_FORM_GNU_addr_index)
117 return (FC == FC_Address);
118 if (Form == DW_FORM_GNU_str_index)
119 return (FC == FC_String);
120 // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
121 // Don't check for DWARF version here, as some producers may still do this
122 // by mistake.
123 if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
124 FC == FC_SectionOffset)
125 return true;
126 return false;
127 }
128
76129 bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
77130 const DWARFUnit *cu) {
78131 bool indirect = false;
154207 break;
155208 case DW_FORM_string:
156209 Value.cstr = data.getCStr(offset_ptr);
157 // Set the string value to also be the data for inlined cstr form
158 // values only so we can tell the differnence between DW_FORM_string
159 // and DW_FORM_strp form values
160 Value.data = (const uint8_t*)Value.cstr;
161210 break;
162211 case DW_FORM_indirect:
163212 Form = data.getULEB128(offset_ptr);
312361 DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
313362 DataExtractor debug_str_data(cu->getStringSection(), true, 0);
314363 DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0);
315 uint64_t uvalue = getUnsigned();
364 uint64_t uvalue = Value.uval;
316365 bool cu_relative_offset = false;
317366
318367 switch (Form) {
335384 case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break;
336385 case DW_FORM_string:
337386 OS << '"';
338 OS.write_escaped(getAsCString(NULL));
387 OS.write_escaped(Value.cstr);
339388 OS << '"';
340389 break;
341390 case DW_FORM_exprloc:
367416 }
368417 break;
369418
370 case DW_FORM_sdata: OS << getSigned(); break;
371 case DW_FORM_udata: OS << getUnsigned(); break;
419 case DW_FORM_sdata: OS << Value.sval; break;
420 case DW_FORM_udata: OS << Value.uval; break;
372421 case DW_FORM_strp: {
373422 OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
374 const char* dbg_str = getAsCString(cu);
375 if (dbg_str) {
423 Optional DbgStr = getAsCString(cu);
424 if (DbgStr.hasValue()) {
376425 OS << '"';
377 OS.write_escaped(dbg_str);
426 OS.write_escaped(DbgStr.getValue());
378427 OS << '"';
379428 }
380429 break;
381430 }
382431 case DW_FORM_GNU_str_index: {
383432 OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
384 const char *dbg_str = getAsCString(cu);
385 if (dbg_str) {
433 Optional DbgStr = getAsCString(cu);
434 if (DbgStr.hasValue()) {
386435 OS << '"';
387 OS.write_escaped(dbg_str);
436 OS.write_escaped(DbgStr.getValue());
388437 OS << '"';
389438 }
390439 break;
433482 OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0));
434483 }
435484
436 const char *DWARFFormValue::getAsCString(const DWARFUnit *CU) const {
437 if (isInlinedCStr())
485 Optional DWARFFormValue::getAsCString(const DWARFUnit *U) const {
486 if (!isFormClass(FC_String))
487 return None;
488 if (Form == DW_FORM_string)
438489 return Value.cstr;
439 if (!CU)
440 return NULL;
490 if (U == 0)
491 return None;
441492 uint32_t Offset = Value.uval;
442493 if (Form == DW_FORM_GNU_str_index) {
443494 uint32_t StrOffset;
444 if (!CU->getStringOffsetSectionItem(Offset, StrOffset))
445 return NULL;
495 if (!U->getStringOffsetSectionItem(Offset, StrOffset))
496 return None;
446497 Offset = StrOffset;
447498 }
448 return CU->getStringExtractor().getCStr(&Offset);
449 }
450
451 uint64_t DWARFFormValue::getAsAddress(const DWARFUnit *CU) const {
452 if (!CU)
453 return 0;
499 if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
500 return Str;
501 }
502 return None;
503 }
504
505 Optional DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
506 if (!isFormClass(FC_Address))
507 return None;
454508 if (Form == DW_FORM_GNU_addr_index) {
455509 uint32_t Index = Value.uval;
456 uint64_t Address;
457 if (!CU->getAddrOffsetSectionItem(Index, Address))
458 return 0;
459 return Address;
510 uint64_t Result;
511 if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result))
512 return None;
513 return Result;
460514 }
461515 return Value.uval;
462516 }
463517
464 uint64_t DWARFFormValue::getReference(const DWARFUnit *cu) const {
465 uint64_t die_offset = Value.uval;
518 Optional DWARFFormValue::getAsReference(const DWARFUnit *U) const {
519 if (!isFormClass(FC_Reference))
520 return None;
466521 switch (Form) {
467522 case DW_FORM_ref1:
468523 case DW_FORM_ref2:
469524 case DW_FORM_ref4:
470525 case DW_FORM_ref8:
471526 case DW_FORM_ref_udata:
472 die_offset += (cu ? cu->getOffset() : 0);
473 break;
527 if (U == 0)
528 return None;
529 return Value.uval + U->getOffset();
530 case DW_FORM_ref_addr:
531 return Value.uval;
532 // FIXME: Add proper support for DW_FORM_ref_sig8
474533 default:
475 break;
476 }
477
478 return die_offset;
479 }
534 return Value.uval;
535 }
536 }
537
538 Optional DWARFFormValue::getAsSectionOffset() const {
539 if (!isFormClass(FC_SectionOffset))
540 return None;
541 return Value.uval;
542 }
543
544 Optional DWARFFormValue::getAsUnsignedConstant() const {
545 if (!isFormClass(FC_Constant) || Form == DW_FORM_sdata)
546 return None;
547 return Value.uval;
548 }
143143 if (DieArray.empty())
144144 return FailValue;
145145 return DieArray[0]
146 .getAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, FailValue);
146 .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
147147 }
148148
149149 void DWARFUnit::setDIERelations() {
250250 // If CU DIE was just parsed, copy several attribute values from it.
251251 if (!HasCUDie) {
252252 uint64_t BaseAddr =
253 DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U);
254 if (BaseAddr == -1U)
255 BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0);
253 DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
254 if (BaseAddr == -1ULL)
255 BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
256256 setBaseAddress(BaseAddr);
257 AddrOffsetSectionBase =
258 DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_addr_base, 0);
259 RangeSectionBase =
260 DieArray[0].getAttributeValueAsReference(this, DW_AT_GNU_ranges_base, 0);
257 AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
258 this, DW_AT_GNU_addr_base, 0);
259 RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
260 this, DW_AT_GNU_ranges_base, 0);
261261 }
262262
263263 setDIERelations();
2727 EXPECT_EQ(0, DWARFFormValue::getFixedFormSizes(16, 2));
2828 }
2929
30 bool isFormClass(uint16_t Form, DWARFFormValue::FormClass FC) {
31 return DWARFFormValue(Form).isFormClass(FC);
32 }
33
34 TEST(DWARFFormValue, FormClass) {
35 EXPECT_TRUE(isFormClass(DW_FORM_addr, DWARFFormValue::FC_Address));
36 EXPECT_FALSE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Address));
37 EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Constant));
38 EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_SectionOffset));
39 EXPECT_TRUE(
40 isFormClass(DW_FORM_sec_offset, DWARFFormValue::FC_SectionOffset));
41 EXPECT_TRUE(isFormClass(DW_FORM_GNU_str_index, DWARFFormValue::FC_String));
42 EXPECT_TRUE(isFormClass(DW_FORM_GNU_addr_index, DWARFFormValue::FC_Address));
43 EXPECT_FALSE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Address));
44 EXPECT_TRUE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Reference));
45 }
46
3047 } // end anonymous namespace