llvm.org GIT mirror llvm / 0ea156d
[DWARF] Modification of code for the verification of .debug_info section. Summary: This patch modifies the handleDebugInfo() function so that we verify the contents of each unit in the .debug_info section only if its header has been successfully verified. This change will allow for more/different verification checks depending on the type of the unit since from dwarf5, the .debug_info section may consist of different types of units. Subscribers: aprantl Differential Revision: https://reviews.llvm.org/D35521 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308245 91177308-0d34-0410-b5e6-96231b3b80d8 Spyridoula Gravani 2 years ago
4 changed file(s) with 302 addition(s) and 65 deletion(s). Raw diff Collapse all Expand all
3030 /// can verify each reference points to a valid DIE and not an offset that
3131 /// lies between to valid DIEs.
3232 std::map> ReferenceToDIEOffsets;
33 uint32_t NumDebugInfoErrors = 0;
3433 uint32_t NumDebugLineErrors = 0;
3534 uint32_t NumAppleNamesErrors = 0;
3635
4948 /// \param Offset A reference to the offset start of the unit. The offset will
5049 /// be updated to point to the next unit in .debug_info
5150 /// \param UnitIndex The index of the unit to be verified
51 /// \param UnitType A reference to the type of the unit
5252 /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is
5353 /// in 64-bit format.
5454 ///
5555 /// \returns true if the header is verified successfully, false otherwise.
5656 bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
57 uint32_t *Offset, unsigned UnitIndex,
57 uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
5858 bool &isUnitDWARF64);
5959
60
61 bool verifyUnitContents(DWARFUnit Unit);
6062 /// Verifies the attribute's DWARF attribute and its value.
6163 ///
6264 /// This function currently checks for:
6567 ///
6668 /// \param Die The DWARF DIE that owns the attribute value
6769 /// \param AttrValue The DWARF attribute value to check
68 void verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue);
70 ///
71 /// \returns NumErrors The number of errors occured during verification of
72 /// attributes' values in a .debug_info section unit
73 unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
74 DWARFAttribute &AttrValue);
6975
7076 /// Verifies the attribute's DWARF form.
7177 ///
7682 ///
7783 /// \param Die The DWARF DIE that owns the attribute value
7884 /// \param AttrValue The DWARF attribute value to check
79 void verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
85 ///
86 /// \returns NumErrors The number of errors occured during verification of
87 /// attributes' forms in a .debug_info section unit
88 unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
8089
8190 /// Verifies the all valid references that were found when iterating through
8291 /// all of the DIE attributes.
8594 /// offset matches. This helps to ensure if a DWARF link phase moved things
8695 /// around, that it doesn't create invalid references by failing to relocate
8796 /// CU relative and absolute references.
88 void verifyDebugInfoReferences();
97 ///
98 /// \returns NumErrors The number of errors occured during verification of
99 /// references for the .debug_info section
100 unsigned verifyDebugInfoReferences();
89101
90102 /// Verify the the DW_AT_stmt_list encoding and value and ensure that no
91103 /// compile units that have the same DW_AT_stmt_list value.
101113 public:
102114 DWARFVerifier(raw_ostream &S, DWARFContext &D)
103115 : OS(S), DCtx(D) {}
104 /// Verify the unit header chain in the .debug_info section.
105 ///
106 /// Any errors are reported to the stream that this object was
107 /// constructed with.
108 ///
109 /// \returns true if the unit header chain verifies successfully, false
110 /// otherwise.
111 bool handleDebugInfoUnitHeaderChain();
112116 /// Verify the information in the .debug_info section.
113117 ///
114118 /// Any errors are reported to the stream that was this object was
413413 bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
414414 bool Success = true;
415415 DWARFVerifier verifier(OS, *this);
416 if (!verifier.handleDebugInfoUnitHeaderChain())
417 Success = false;
418416 if (DumpType == DIDT_All || DumpType == DIDT_Info) {
419417 if (!verifier.handleDebugInfo())
420418 Success = false;
2424 using namespace object;
2525
2626 bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
27 uint32_t *Offset, unsigned UnitIndex,
28 bool &isUnitDWARF64) {
27 uint32_t *Offset, unsigned UnitIndex,
28 uint8_t &UnitType, bool &isUnitDWARF64) {
2929 uint32_t AbbrOffset, Length;
30 uint8_t AddrSize = 0, UnitType = 0;
30 uint8_t AddrSize = 0;
3131 uint16_t Version;
3232 bool Success = true;
3333
5454 AbbrOffset = DebugInfoData.getU32(Offset);
5555 ValidType = DWARFUnit::isValidUnitType(UnitType);
5656 } else {
57 UnitType = 0;
5758 AbbrOffset = DebugInfoData.getU32(Offset);
5859 AddrSize = DebugInfoData.getU8(Offset);
5960 }
8586 return Success;
8687 }
8788
88 bool DWARFVerifier::handleDebugInfoUnitHeaderChain() {
89 bool DWARFVerifier::verifyUnitContents(DWARFUnit Unit) {
90 uint32_t NumUnitErrors = 0;
91 unsigned NumDies = Unit.getNumDIEs();
92 for (unsigned I = 0; I < NumDies; ++I) {
93 auto Die = Unit.getDIEAtIndex(I);
94 if (Die.getTag() == DW_TAG_null)
95 continue;
96 for (auto AttrValue : Die.attributes()) {
97 NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
98 NumUnitErrors += verifyDebugInfoForm(Die, AttrValue);
99 }
100 }
101 return NumUnitErrors == 0;
102 }
103
104 bool DWARFVerifier::handleDebugInfo() {
89105 OS << "Verifying .debug_info Unit Header Chain...\n";
90106
91107 DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(),
92108 0);
93 uint32_t Offset = 0, UnitIdx = 0;
109 uint32_t NumDebugInfoErrors = 0;
110 uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
111 uint8_t UnitType = 0;
94112 bool isUnitDWARF64 = false;
95 bool Success = true;
113 bool isHeaderChainValid = true;
96114 bool hasDIE = DebugInfoData.isValidOffset(Offset);
97115 while (hasDIE) {
98 if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, isUnitDWARF64)) {
99 Success = false;
116 OffsetStart = Offset;
117 if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
118 isUnitDWARF64)) {
119 isHeaderChainValid = false;
100120 if (isUnitDWARF64)
101121 break;
122 } else {
123 std::unique_ptr Unit;
124 switch (UnitType) {
125 case dwarf::DW_UT_type:
126 case dwarf::DW_UT_split_type: {
127 DWARFUnitSection TUSection{};
128 Unit.reset(new DWARFTypeUnit(
129 DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(),
130 &DCtx.getRangeSection(), DCtx.getStringSection(),
131 DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(),
132 DCtx.getLineSection(), DCtx.isLittleEndian(), false, TUSection,
133 nullptr));
134 break;
135 }
136 case dwarf::DW_UT_skeleton:
137 case dwarf::DW_UT_split_compile:
138 case dwarf::DW_UT_compile:
139 case dwarf::DW_UT_partial:
140 // UnitType = 0 means that we are
141 // verifying a compile unit in DWARF v4.
142 case 0: {
143 DWARFUnitSection CUSection{};
144 Unit.reset(new DWARFCompileUnit(
145 DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(),
146 &DCtx.getRangeSection(), DCtx.getStringSection(),
147 DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(),
148 DCtx.getLineSection(), DCtx.isLittleEndian(), false, CUSection,
149 nullptr));
150 break;
151 }
152 default: { llvm_unreachable("Invalid UnitType."); }
153 }
154 Unit->extract(DebugInfoData, &OffsetStart);
155 if (!verifyUnitContents(*Unit))
156 ++NumDebugInfoErrors;
102157 }
103158 hasDIE = DebugInfoData.isValidOffset(Offset);
104159 ++UnitIdx;
105160 }
106161 if (UnitIdx == 0 && !hasDIE) {
107162 OS << "Warning: .debug_info is empty.\n";
108 Success = true;
109 }
110 return Success;
111 }
112
113 void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
114 DWARFAttribute &AttrValue) {
163 isHeaderChainValid = true;
164 }
165 NumDebugInfoErrors += verifyDebugInfoReferences();
166 return (isHeaderChainValid && NumDebugInfoErrors == 0);
167 }
168
169 unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
170 DWARFAttribute &AttrValue) {
171 unsigned NumErrors = 0;
115172 const auto Attr = AttrValue.Attr;
116173 switch (Attr) {
117174 case DW_AT_ranges:
118175 // Make sure the offset in the DW_AT_ranges attribute is valid.
119176 if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
120177 if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
121 ++NumDebugInfoErrors;
178 ++NumErrors;
122179 OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
123180 "bounds:\n";
124181 Die.dump(OS, 0);
125182 OS << "\n";
126183 }
127184 } else {
128 ++NumDebugInfoErrors;
185 ++NumErrors;
129186 OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
130187 Die.dump(OS, 0);
131188 OS << "\n";
135192 // Make sure the offset in the DW_AT_stmt_list attribute is valid.
136193 if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
137194 if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
138 ++NumDebugInfoErrors;
195 ++NumErrors;
139196 OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
140197 "bounds: "
141198 << format("0x%08" PRIx32, *SectionOffset) << "\n";
143200 OS << "\n";
144201 }
145202 } else {
146 ++NumDebugInfoErrors;
203 ++NumErrors;
147204 OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
148205 Die.dump(OS, 0);
149206 OS << "\n";
153210 default:
154211 break;
155212 }
156 }
157
158 void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
159 DWARFAttribute &AttrValue) {
213 return NumErrors;
214 }
215
216 unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
217 DWARFAttribute &AttrValue) {
218 unsigned NumErrors = 0;
160219 const auto Form = AttrValue.Value.getForm();
161220 switch (Form) {
162221 case DW_FORM_ref1:
172231 auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
173232 auto CUOffset = AttrValue.Value.getRawUValue();
174233 if (CUOffset >= CUSize) {
175 ++NumDebugInfoErrors;
234 ++NumErrors;
176235 OS << "error: " << FormEncodingString(Form) << " CU offset "
177236 << format("0x%08" PRIx32, CUOffset)
178237 << " is invalid (must be less than CU size of "
194253 assert(RefVal);
195254 if (RefVal) {
196255 if (*RefVal >= DCtx.getInfoSection().Data.size()) {
197 ++NumDebugInfoErrors;
256 ++NumErrors;
198257 OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
199258 "bounds:\n";
200259 Die.dump(OS, 0);
211270 auto SecOffset = AttrValue.Value.getAsSectionOffset();
212271 assert(SecOffset); // DW_FORM_strp is a section offset.
213272 if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
214 ++NumDebugInfoErrors;
273 ++NumErrors;
215274 OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
216275 Die.dump(OS, 0);
217276 OS << "\n";
221280 default:
222281 break;
223282 }
224 }
225
226 void DWARFVerifier::verifyDebugInfoReferences() {
283 return NumErrors;
284 }
285
286 unsigned DWARFVerifier::verifyDebugInfoReferences() {
227287 // Take all references and make sure they point to an actual DIE by
228288 // getting the DIE by offset and emitting an error
229289 OS << "Verifying .debug_info references...\n";
290 unsigned NumErrors = 0;
230291 for (auto Pair : ReferenceToDIEOffsets) {
231292 auto Die = DCtx.getDIEForOffset(Pair.first);
232293 if (Die)
233294 continue;
234 ++NumDebugInfoErrors;
295 ++NumErrors;
235296 OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
236297 << ". Offset is in between DIEs:\n";
237298 for (auto Offset : Pair.second) {
241302 }
242303 OS << "\n";
243304 }
244 }
245
246 bool DWARFVerifier::handleDebugInfo() {
247 NumDebugInfoErrors = 0;
248 OS << "Verifying .debug_info...\n";
249 for (const auto &CU : DCtx.compile_units()) {
250 unsigned NumDies = CU->getNumDIEs();
251 for (unsigned I = 0; I < NumDies; ++I) {
252 auto Die = CU->getDIEAtIndex(I);
253 const auto Tag = Die.getTag();
254 if (Tag == DW_TAG_null)
255 continue;
256 for (auto AttrValue : Die.attributes()) {
257 verifyDebugInfoAttribute(Die, AttrValue);
258 verifyDebugInfoForm(Die, AttrValue);
259 }
260 }
261 }
262 verifyDebugInfoReferences();
263 return NumDebugInfoErrors == 0;
305 return NumErrors;
264306 }
265307
266308 void DWARFVerifier::verifyDebugLineStmtOffsets() {
0 # RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \
1 # RUN: | not llvm-dwarfdump -verify - \
2 # RUN: | FileCheck %s
3
4 # CHECK: Verifying .debug_info Unit Header Chain...
5 # CHECK-NEXT: error: DIE has invalid DW_AT_stmt_list encoding:{{[[:space:]]}}
6 # CHECK-NEXT: 0x0000000c: DW_TAG_compile_unit [1] *
7 # CHECK-NEXT: DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000000] = "clang version 5.0.0 (trunk 308185) (llvm/trunk 308186)")
8 # CHECK-NEXT: DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
9 # CHECK-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000037] = "basic.c")
10 # CHECK-NEXT: DW_AT_stmt_list [DW_FORM_strx4] ( indexed (00000000) string = )
11 # CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000003f] = "/Users/sgravani/Development/tests")
12 # CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
13 # CHECK-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000016){{[[:space:]]}}
14 # CHECK-NEXT: Units[2] - start offset: 0x00000068
15 # CHECK-NEXT: Error: The length for this unit is too large for the .debug_info provided.
16 # CHECK-NEXT: Error: The unit type encoding is not valid.
17
18
19 .section __TEXT,__text,regular,pure_instructions
20 .globl _main ## -- Begin function main
21 .p2align 4, 0x90
22 _main: ## @main
23 Lfunc_begin0:
24 .file 1 "basic.c"
25 .loc 1 1 0 ## basic.c:1:0
26 .cfi_startproc
27 ## BB#0: ## %entry
28 pushq %rbp
29 Lcfi0:
30 .cfi_def_cfa_offset 16
31 Lcfi1:
32 .cfi_offset %rbp, -16
33 movq %rsp, %rbp
34 Lcfi2:
35 .cfi_def_cfa_register %rbp
36 xorl %eax, %eax
37 movl $0, -4(%rbp)
38 Ltmp0:
39 .loc 1 2 7 prologue_end ## basic.c:2:7
40 movl $1, -8(%rbp)
41 .loc 1 3 3 ## basic.c:3:3
42 popq %rbp
43 retq
44 Ltmp1:
45 Lfunc_end0:
46 .cfi_endproc
47 ## -- End function
48 .section __DWARF,__debug_str,regular,debug
49 Linfo_string:
50 .asciz "clang version 5.0.0 (trunk 308185) (llvm/trunk 308186)" ## string offset=0
51 .asciz "basic.c" ## string offset=55
52 .asciz "/Users/sgravani/Development/tests" ## string offset=63
53 .asciz "main" ## string offset=97
54 .asciz "int" ## string offset=102
55 .asciz "a" ## string offset=106
56 .section __DWARF,__debug_abbrev,regular,debug
57 Lsection_abbrev:
58 .byte 1 ## Abbreviation Code
59 .byte 17 ## DW_TAG_compile_unit
60 .byte 1 ## DW_CHILDREN_yes
61 .byte 37 ## DW_AT_producer
62 .byte 14 ## DW_FORM_strp
63 .byte 19 ## DW_AT_language
64 .byte 5 ## DW_FORM_data2
65 .byte 3 ## DW_AT_name
66 .byte 14 ## DW_FORM_strp
67 .byte 16 ## DW_AT_stmt_list
68 .byte 40 ## DW_FORM_sec_offset -- error: DIE has invalid DW_AT_stmt_list encoding:
69 .byte 27 ## DW_AT_comp_dir
70 .byte 14 ## DW_FORM_strp
71 .byte 17 ## DW_AT_low_pc
72 .byte 1 ## DW_FORM_addr
73 .byte 18 ## DW_AT_high_pc
74 .byte 6 ## DW_FORM_data4
75 .byte 0 ## EOM(1)
76 .byte 0 ## EOM(2)
77 .byte 2 ## Abbreviation Code
78 .byte 46 ## DW_TAG_subprogram
79 .byte 1 ## DW_CHILDREN_yes
80 .byte 17 ## DW_AT_low_pc
81 .byte 1 ## DW_FORM_addr
82 .byte 18 ## DW_AT_high_pc
83 .byte 6 ## DW_FORM_data4
84 .byte 64 ## DW_AT_frame_base
85 .byte 24 ## DW_FORM_exprloc
86 .byte 3 ## DW_AT_name
87 .byte 14 ## DW_FORM_strp
88 .byte 58 ## DW_AT_decl_file
89 .byte 11 ## DW_FORM_data1
90 .byte 59 ## DW_AT_decl_line
91 .byte 11 ## DW_FORM_data1
92 .byte 39 ## DW_AT_prototyped
93 .byte 25 ## DW_FORM_flag_present
94 .byte 73 ## DW_AT_type
95 .byte 19 ## DW_FORM_ref4
96 .byte 63 ## DW_AT_external
97 .byte 25 ## DW_FORM_flag_present
98 .byte 0 ## EOM(1)
99 .byte 0 ## EOM(2)
100 .byte 3 ## Abbreviation Code
101 .byte 52 ## DW_TAG_variable
102 .byte 0 ## DW_CHILDREN_no
103 .byte 2 ## DW_AT_location
104 .byte 24 ## DW_FORM_exprloc
105 .byte 3 ## DW_AT_name
106 .byte 14 ## DW_FORM_strp
107 .byte 58 ## DW_AT_decl_file
108 .byte 11 ## DW_FORM_data1
109 .byte 59 ## DW_AT_decl_line
110 .byte 11 ## DW_FORM_data1
111 .byte 73 ## DW_AT_type
112 .byte 19 ## DW_FORM_ref4
113 .byte 0 ## EOM(1)
114 .byte 0 ## EOM(2)
115 .byte 4 ## Abbreviation Code
116 .byte 36 ## DW_TAG_base_type
117 .byte 0 ## DW_CHILDREN_no
118 .byte 3 ## DW_AT_name
119 .byte 14 ## DW_FORM_strp
120 .byte 62 ## DW_AT_encoding
121 .byte 11 ## DW_FORM_data1
122 .byte 11 ## DW_AT_byte_size
123 .byte 11 ## DW_FORM_data1
124 .byte 0 ## EOM(1)
125 .byte 0 ## EOM(2)
126 .byte 0 ## EOM(3)
127 .section __DWARF,__debug_info,regular,debug
128 Lsection_info:
129 Lcu_begin0:
130 .long 87 ## Length of Unit
131 .short 5 ## DWARF version number
132 .byte 1 ## DWARF Unit Type
133 .byte 8 ## Address Size (in bytes)
134 Lset0 = Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section
135 .long Lset0
136 .byte 1 ## Abbrev [1] 0xc:0x4f DW_TAG_compile_unit
137 .long 0 ## DW_AT_producer
138 .short 12 ## DW_AT_language
139 .long 55 ## DW_AT_name
140 Lset1 = Lline_table_start0-Lsection_line ## DW_AT_stmt_list
141 .long Lset1
142 .long 63 ## DW_AT_comp_dir
143 .quad Lfunc_begin0 ## DW_AT_low_pc
144 Lset2 = Lfunc_end0-Lfunc_begin0 ## DW_AT_high_pc
145 .long Lset2
146 .byte 2 ## Abbrev [2] 0x2b:0x28 DW_TAG_subprogram
147 .quad Lfunc_begin0 ## DW_AT_low_pc
148 Lset3 = Lfunc_end0-Lfunc_begin0 ## DW_AT_high_pc
149 .long Lset3
150 .byte 1 ## DW_AT_frame_base
151 .byte 86
152 .long 97 ## DW_AT_name
153 .byte 1 ## DW_AT_decl_file
154 .byte 1 ## DW_AT_decl_line
155 ## DW_AT_prototyped
156 .long 83 ## DW_AT_type
157 ## DW_AT_external
158 .byte 3 ## Abbrev [3] 0x44:0xe DW_TAG_variable
159 .byte 2 ## DW_AT_location
160 .byte 145
161 .byte 120
162 .long 106 ## DW_AT_name
163 .byte 1 ## DW_AT_decl_file
164 .byte 2 ## DW_AT_decl_line
165 .long 83 ## DW_AT_type
166 .byte 0 ## End Of Children Mark
167 .byte 4 ## Abbrev [4] 0x53:0x7 DW_TAG_base_type
168 .long 102 ## DW_AT_name
169 .byte 5 ## DW_AT_encoding
170 .byte 4 ## DW_AT_byte_size
171 .byte 0 ## End Of Children Mark
172 Lcu_begin1:
173 .long 9 ## Length of Unit
174 .short 5 ## DWARF version number
175 .byte 1 ## DWARF Unit Type
176 .byte 4 ## Address Size (in bytes)
177 .long 0 ## Abbrev offset
178 .byte 0
179 Ltu_begin0:
180 .long 26 ## Length of Unit -- Error: The length for this unit is too large for the .debug_info provided.
181 .short 5 ## DWARF version number
182 .byte 0 ## DWARF Unit Type
183 .byte 4 ## Address Size (in bytes)
184 .long 0
185 .quad 0
186 .long 0
187 .byte 0
188
189 .subsections_via_symbols
190 .section __DWARF,__debug_line,regular,debug
191 Lsection_line:
192 Lline_table_start0: