blob: 0eef0f6a82bf5a05fd04238c21b4f7fc7cbed106 [file] [log] [blame]
Greg Claytonb8c162b2017-05-03 16:02:29 +00001//===- DWARFVerifier.cpp --------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Greg Claytonb8c162b2017-05-03 16:02:29 +00006//
7//===----------------------------------------------------------------------===//
Greg Claytonb8c162b2017-05-03 16:02:29 +00008#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
Pavel Labath79cd9422018-03-22 14:50:44 +00009#include "llvm/ADT/SmallSet.h"
Greg Claytonb8c162b2017-05-03 16:02:29 +000010#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
11#include "llvm/DebugInfo/DWARF/DWARFContext.h"
12#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
13#include "llvm/DebugInfo/DWARF/DWARFDie.h"
George Rimar144e4c52017-10-27 10:42:04 +000014#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
Greg Claytonb8c162b2017-05-03 16:02:29 +000015#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16#include "llvm/DebugInfo/DWARF/DWARFSection.h"
Pavel Labath906b7772018-03-16 10:02:16 +000017#include "llvm/Support/DJB.h"
George Rimar144e4c52017-10-27 10:42:04 +000018#include "llvm/Support/FormatVariadic.h"
Jonas Devlieghere69217532018-03-09 09:56:24 +000019#include "llvm/Support/WithColor.h"
Greg Claytonb8c162b2017-05-03 16:02:29 +000020#include "llvm/Support/raw_ostream.h"
21#include <map>
22#include <set>
23#include <vector>
24
25using namespace llvm;
26using namespace dwarf;
27using namespace object;
28
Jonas Devlieghere58910602017-09-14 11:33:42 +000029DWARFVerifier::DieRangeInfo::address_range_iterator
30DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) {
31 auto Begin = Ranges.begin();
32 auto End = Ranges.end();
33 auto Pos = std::lower_bound(Begin, End, R);
34
35 if (Pos != End) {
36 if (Pos->intersects(R))
37 return Pos;
38 if (Pos != Begin) {
39 auto Iter = Pos - 1;
40 if (Iter->intersects(R))
41 return Iter;
42 }
43 }
44
45 Ranges.insert(Pos, R);
46 return Ranges.end();
47}
48
49DWARFVerifier::DieRangeInfo::die_range_info_iterator
50DWARFVerifier::DieRangeInfo::insert(const DieRangeInfo &RI) {
51 auto End = Children.end();
52 auto Iter = Children.begin();
53 while (Iter != End) {
54 if (Iter->intersects(RI))
55 return Iter;
56 ++Iter;
57 }
58 Children.insert(RI);
59 return Children.end();
60}
61
62bool DWARFVerifier::DieRangeInfo::contains(const DieRangeInfo &RHS) const {
63 // Both list of ranges are sorted so we can make this fast.
64
65 if (Ranges.empty() || RHS.Ranges.empty())
66 return false;
67
68 // Since the ranges are sorted we can advance where we start searching with
69 // this object's ranges as we traverse RHS.Ranges.
70 auto End = Ranges.end();
71 auto Iter = findRange(RHS.Ranges.front());
72
73 // Now linearly walk the ranges in this object and see if they contain each
74 // ranges from RHS.Ranges.
75 for (const auto &R : RHS.Ranges) {
76 while (Iter != End) {
77 if (Iter->contains(R))
78 break;
79 ++Iter;
80 }
81 if (Iter == End)
82 return false;
83 }
84 return true;
85}
86
87bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const {
88 if (Ranges.empty() || RHS.Ranges.empty())
89 return false;
90
91 auto End = Ranges.end();
92 auto Iter = findRange(RHS.Ranges.front());
93 for (const auto &R : RHS.Ranges) {
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +000094 if (Iter == End)
Jonas Devlieghered585a202017-09-14 17:46:23 +000095 return false;
Jonas Devlieghere58910602017-09-14 11:33:42 +000096 if (R.HighPC <= Iter->LowPC)
97 continue;
98 while (Iter != End) {
99 if (Iter->intersects(R))
100 return true;
101 ++Iter;
102 }
103 }
104
105 return false;
106}
107
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000108bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000109 uint32_t *Offset, unsigned UnitIndex,
110 uint8_t &UnitType, bool &isUnitDWARF64) {
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000111 uint32_t AbbrOffset, Length;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000112 uint8_t AddrSize = 0;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000113 uint16_t Version;
114 bool Success = true;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000115
116 bool ValidLength = false;
117 bool ValidVersion = false;
118 bool ValidAddrSize = false;
119 bool ValidType = true;
120 bool ValidAbbrevOffset = true;
121
122 uint32_t OffsetStart = *Offset;
123 Length = DebugInfoData.getU32(Offset);
124 if (Length == UINT32_MAX) {
125 isUnitDWARF64 = true;
126 OS << format(
127 "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",
128 UnitIndex);
129 return false;
130 }
131 Version = DebugInfoData.getU16(Offset);
132
133 if (Version >= 5) {
134 UnitType = DebugInfoData.getU8(Offset);
135 AddrSize = DebugInfoData.getU8(Offset);
136 AbbrOffset = DebugInfoData.getU32(Offset);
Jonas Devliegheref2fa9eb2017-10-06 22:27:31 +0000137 ValidType = dwarf::isUnitType(UnitType);
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000138 } else {
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000139 UnitType = 0;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000140 AbbrOffset = DebugInfoData.getU32(Offset);
141 AddrSize = DebugInfoData.getU8(Offset);
142 }
143
144 if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
145 ValidAbbrevOffset = false;
146
147 ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
148 ValidVersion = DWARFContext::isSupportedVersion(Version);
149 ValidAddrSize = AddrSize == 4 || AddrSize == 8;
150 if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
151 !ValidType) {
152 Success = false;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000153 error() << format("Units[%d] - start offset: 0x%08x \n", UnitIndex,
154 OffsetStart);
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000155 if (!ValidLength)
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000156 note() << "The length for this unit is too "
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +0000157 "large for the .debug_info provided.\n";
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000158 if (!ValidVersion)
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000159 note() << "The 16 bit unit header version is not valid.\n";
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000160 if (!ValidType)
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000161 note() << "The unit type encoding is not valid.\n";
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000162 if (!ValidAbbrevOffset)
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000163 note() << "The offset into the .debug_abbrev section is "
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +0000164 "not valid.\n";
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000165 if (!ValidAddrSize)
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000166 note() << "The address size is unsupported.\n";
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000167 }
168 *Offset = OffsetStart + Length + 4;
169 return Success;
170}
171
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +0000172unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit) {
Paul Robinson508b0812018-08-08 23:50:22 +0000173 unsigned NumUnitErrors = 0;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000174 unsigned NumDies = Unit.getNumDIEs();
175 for (unsigned I = 0; I < NumDies; ++I) {
176 auto Die = Unit.getDIEAtIndex(I);
Jonas Devlieghereb3227422018-09-21 07:50:21 +0000177
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000178 if (Die.getTag() == DW_TAG_null)
179 continue;
Jonas Devlieghereb3227422018-09-21 07:50:21 +0000180
181 bool HasTypeAttr = false;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000182 for (auto AttrValue : Die.attributes()) {
183 NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
184 NumUnitErrors += verifyDebugInfoForm(Die, AttrValue);
Jonas Devlieghereb3227422018-09-21 07:50:21 +0000185 HasTypeAttr |= (AttrValue.Attr == DW_AT_type);
186 }
187
188 if (!HasTypeAttr && (Die.getTag() == DW_TAG_formal_parameter ||
189 Die.getTag() == DW_TAG_variable ||
190 Die.getTag() == DW_TAG_array_type)) {
191 error() << "DIE with tag " << TagString(Die.getTag())
192 << " is missing type attribute:\n";
193 dump(Die) << '\n';
194 NumUnitErrors++;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000195 }
Vedant Kumar5931b4e2018-10-05 20:37:17 +0000196 NumUnitErrors += verifyDebugInfoCallSite(Die);
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000197 }
Jonas Devlieghere58910602017-09-14 11:33:42 +0000198
Jonas Devliegheref2fa9eb2017-10-06 22:27:31 +0000199 DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
200 if (!Die) {
201 error() << "Compilation unit without DIE.\n";
202 NumUnitErrors++;
Paul Robinson508b0812018-08-08 23:50:22 +0000203 return NumUnitErrors;
Jonas Devliegheref2fa9eb2017-10-06 22:27:31 +0000204 }
205
206 if (!dwarf::isUnitType(Die.getTag())) {
207 error() << "Compilation unit root DIE is not a unit DIE: "
208 << dwarf::TagString(Die.getTag()) << ".\n";
Jonas Devlieghere35fdaa92017-09-28 15:57:50 +0000209 NumUnitErrors++;
210 }
211
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +0000212 uint8_t UnitType = Unit.getUnitType();
213 if (!DWARFUnit::isMatchingUnitTypeAndTag(UnitType, Die.getTag())) {
Jonas Devliegheref2fa9eb2017-10-06 22:27:31 +0000214 error() << "Compilation unit type (" << dwarf::UnitTypeString(UnitType)
215 << ") and root DIE (" << dwarf::TagString(Die.getTag())
216 << ") do not match.\n";
217 NumUnitErrors++;
218 }
219
220 DieRangeInfo RI;
221 NumUnitErrors += verifyDieRanges(Die, RI);
222
Paul Robinson508b0812018-08-08 23:50:22 +0000223 return NumUnitErrors;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000224}
225
Vedant Kumar5931b4e2018-10-05 20:37:17 +0000226unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
227 if (Die.getTag() != DW_TAG_call_site)
228 return 0;
229
230 DWARFDie Curr = Die.getParent();
231 for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Die.getParent()) {
232 if (Curr.getTag() == DW_TAG_inlined_subroutine) {
233 error() << "Call site entry nested within inlined subroutine:";
234 Curr.dump(OS);
235 return 1;
236 }
237 }
238
239 if (!Curr.isValid()) {
240 error() << "Call site entry not nested within a valid subprogram:";
241 Die.dump(OS);
242 return 1;
243 }
244
245 Optional<DWARFFormValue> CallAttr =
246 Curr.find({DW_AT_call_all_calls, DW_AT_call_all_source_calls,
247 DW_AT_call_all_tail_calls});
248 if (!CallAttr) {
249 error() << "Subprogram with call site entry has no DW_AT_call attribute:";
250 Curr.dump(OS);
251 Die.dump(OS, /*indent*/ 1);
252 return 1;
253 }
254
255 return 0;
256}
257
Spyridoula Gravanic6ef9872017-07-21 00:51:32 +0000258unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
Spyridoula Gravani364b5352017-07-20 02:06:52 +0000259 unsigned NumErrors = 0;
Spyridoula Gravani364b5352017-07-20 02:06:52 +0000260 if (Abbrev) {
261 const DWARFAbbreviationDeclarationSet *AbbrDecls =
262 Abbrev->getAbbreviationDeclarationSet(0);
263 for (auto AbbrDecl : *AbbrDecls) {
264 SmallDenseSet<uint16_t> AttributeSet;
265 for (auto Attribute : AbbrDecl.attributes()) {
266 auto Result = AttributeSet.insert(Attribute.Attr);
267 if (!Result.second) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000268 error() << "Abbreviation declaration contains multiple "
269 << AttributeString(Attribute.Attr) << " attributes.\n";
Spyridoula Gravanic6ef9872017-07-21 00:51:32 +0000270 AbbrDecl.dump(OS);
Spyridoula Gravani364b5352017-07-20 02:06:52 +0000271 ++NumErrors;
272 }
273 }
274 }
275 }
Spyridoula Gravanic6ef9872017-07-21 00:51:32 +0000276 return NumErrors;
277}
278
279bool DWARFVerifier::handleDebugAbbrev() {
280 OS << "Verifying .debug_abbrev...\n";
281
282 const DWARFObject &DObj = DCtx.getDWARFObj();
283 bool noDebugAbbrev = DObj.getAbbrevSection().empty();
284 bool noDebugAbbrevDWO = DObj.getAbbrevDWOSection().empty();
285
286 if (noDebugAbbrev && noDebugAbbrevDWO) {
287 return true;
288 }
289
290 unsigned NumErrors = 0;
291 if (!noDebugAbbrev)
292 NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrev());
293
294 if (!noDebugAbbrevDWO)
295 NumErrors += verifyAbbrevSection(DCtx.getDebugAbbrevDWO());
Spyridoula Gravani364b5352017-07-20 02:06:52 +0000296 return NumErrors == 0;
297}
298
Paul Robinson508b0812018-08-08 23:50:22 +0000299unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S,
300 DWARFSectionKind SectionKind) {
Rafael Espindolac398e672017-07-19 22:27:28 +0000301 const DWARFObject &DObj = DCtx.getDWARFObj();
Paul Robinson508b0812018-08-08 23:50:22 +0000302 DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0);
303 unsigned NumDebugInfoErrors = 0;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000304 uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
305 uint8_t UnitType = 0;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000306 bool isUnitDWARF64 = false;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000307 bool isHeaderChainValid = true;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000308 bool hasDIE = DebugInfoData.isValidOffset(Offset);
Jonas Devlieghere7ef2c202018-09-21 07:49:29 +0000309 DWARFUnitVector TypeUnitVector;
310 DWARFUnitVector CompileUnitVector;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000311 while (hasDIE) {
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000312 OffsetStart = Offset;
313 if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
314 isUnitDWARF64)) {
315 isHeaderChainValid = false;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000316 if (isUnitDWARF64)
317 break;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000318 } else {
Paul Robinson5f53f072018-05-14 20:32:31 +0000319 DWARFUnitHeader Header;
Paul Robinson508b0812018-08-08 23:50:22 +0000320 Header.extract(DCtx, DebugInfoData, &OffsetStart, SectionKind);
Jonas Devlieghere7ef2c202018-09-21 07:49:29 +0000321 DWARFUnit *Unit;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000322 switch (UnitType) {
323 case dwarf::DW_UT_type:
324 case dwarf::DW_UT_split_type: {
Jonas Devlieghere7ef2c202018-09-21 07:49:29 +0000325 Unit = TypeUnitVector.addUnit(llvm::make_unique<DWARFTypeUnit>(
Paul Robinson508b0812018-08-08 23:50:22 +0000326 DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(),
Wolfgang Pieb6214c112018-10-19 19:23:16 +0000327 &DObj.getLocSection(), DObj.getStringSection(),
328 DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
329 DObj.getLineSection(), DCtx.isLittleEndian(), false,
330 TypeUnitVector));
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000331 break;
332 }
333 case dwarf::DW_UT_skeleton:
334 case dwarf::DW_UT_split_compile:
335 case dwarf::DW_UT_compile:
336 case dwarf::DW_UT_partial:
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +0000337 // UnitType = 0 means that we are verifying a compile unit in DWARF v4.
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000338 case 0: {
Jonas Devlieghere7ef2c202018-09-21 07:49:29 +0000339 Unit = CompileUnitVector.addUnit(llvm::make_unique<DWARFCompileUnit>(
Paul Robinson508b0812018-08-08 23:50:22 +0000340 DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(),
Wolfgang Pieb6214c112018-10-19 19:23:16 +0000341 &DObj.getLocSection(), DObj.getStringSection(),
342 DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(),
343 DObj.getLineSection(), DCtx.isLittleEndian(), false,
344 CompileUnitVector));
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000345 break;
346 }
347 default: { llvm_unreachable("Invalid UnitType."); }
348 }
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +0000349 NumDebugInfoErrors += verifyUnitContents(*Unit);
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000350 }
351 hasDIE = DebugInfoData.isValidOffset(Offset);
352 ++UnitIdx;
353 }
354 if (UnitIdx == 0 && !hasDIE) {
Paul Robinson508b0812018-08-08 23:50:22 +0000355 warn() << "Section is empty.\n";
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000356 isHeaderChainValid = true;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000357 }
Paul Robinson508b0812018-08-08 23:50:22 +0000358 if (!isHeaderChainValid)
359 ++NumDebugInfoErrors;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000360 NumDebugInfoErrors += verifyDebugInfoReferences();
Paul Robinson508b0812018-08-08 23:50:22 +0000361 return NumDebugInfoErrors;
362}
363
364bool DWARFVerifier::handleDebugInfo() {
365 const DWARFObject &DObj = DCtx.getDWARFObj();
Paul Robinson746c22382018-11-07 21:39:09 +0000366 unsigned NumErrors = 0;
Paul Robinson508b0812018-08-08 23:50:22 +0000367
368 OS << "Verifying .debug_info Unit Header Chain...\n";
Paul Robinson746c22382018-11-07 21:39:09 +0000369 DObj.forEachInfoSections([&](const DWARFSection &S) {
370 NumErrors += verifyUnitSection(S, DW_SECT_INFO);
371 });
Paul Robinson508b0812018-08-08 23:50:22 +0000372
373 OS << "Verifying .debug_types Unit Header Chain...\n";
374 DObj.forEachTypesSections([&](const DWARFSection &S) {
Paul Robinson746c22382018-11-07 21:39:09 +0000375 NumErrors += verifyUnitSection(S, DW_SECT_TYPES);
Paul Robinson508b0812018-08-08 23:50:22 +0000376 });
Paul Robinson746c22382018-11-07 21:39:09 +0000377 return NumErrors == 0;
Spyridoula Gravani890eedc2017-07-13 23:25:24 +0000378}
379
Jonas Devlieghere58910602017-09-14 11:33:42 +0000380unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
381 DieRangeInfo &ParentRI) {
Spyridoula Gravanie0ba4152017-07-24 21:04:11 +0000382 unsigned NumErrors = 0;
Jonas Devlieghere58910602017-09-14 11:33:42 +0000383
384 if (!Die.isValid())
385 return NumErrors;
386
Wolfgang Pieb61d8c8d2018-06-20 22:56:37 +0000387 auto RangesOrError = Die.getAddressRanges();
388 if (!RangesOrError) {
389 // FIXME: Report the error.
390 ++NumErrors;
391 llvm::consumeError(RangesOrError.takeError());
392 return NumErrors;
393 }
Jonas Devlieghere58910602017-09-14 11:33:42 +0000394
Wolfgang Pieb61d8c8d2018-06-20 22:56:37 +0000395 DWARFAddressRangesVector Ranges = RangesOrError.get();
Jonas Devlieghere58910602017-09-14 11:33:42 +0000396 // Build RI for this DIE and check that ranges within this DIE do not
397 // overlap.
398 DieRangeInfo RI(Die);
Jonas Devlieghere58910602017-09-14 11:33:42 +0000399
Saleem Abdulrasoolec77a652018-10-28 22:30:48 +0000400 // TODO support object files better
401 //
402 // Some object file formats (i.e. non-MachO) support COMDAT. ELF in
403 // particular does so by placing each function into a section. The DWARF data
404 // for the function at that point uses a section relative DW_FORM_addrp for
405 // the DW_AT_low_pc and a DW_FORM_data4 for the offset as the DW_AT_high_pc.
406 // In such a case, when the Die is the CU, the ranges will overlap, and we
407 // will flag valid conflicting ranges as invalid.
408 //
409 // For such targets, we should read the ranges from the CU and partition them
410 // by the section id. The ranges within a particular section should be
411 // disjoint, although the ranges across sections may overlap. We would map
412 // the child die to the entity that it references and the section with which
413 // it is associated. The child would then be checked against the range
414 // information for the associated section.
415 //
416 // For now, simply elide the range verification for the CU DIEs if we are
417 // processing an object file.
418
Saleem Abdulrasool91242b72018-10-30 23:45:27 +0000419 if (!IsObjectFile || IsMachOObject || Die.getTag() != DW_TAG_compile_unit) {
Saleem Abdulrasoolec77a652018-10-28 22:30:48 +0000420 for (auto Range : Ranges) {
421 if (!Range.valid()) {
422 ++NumErrors;
423 error() << "Invalid address range " << Range << "\n";
424 continue;
425 }
426
427 // Verify that ranges don't intersect.
428 const auto IntersectingRange = RI.insert(Range);
429 if (IntersectingRange != RI.Ranges.end()) {
430 ++NumErrors;
431 error() << "DIE has overlapping address ranges: " << Range << " and "
432 << *IntersectingRange << "\n";
433 break;
434 }
Spyridoula Gravanie0ba4152017-07-24 21:04:11 +0000435 }
436 }
Jonas Devlieghere58910602017-09-14 11:33:42 +0000437
438 // Verify that children don't intersect.
439 const auto IntersectingChild = ParentRI.insert(RI);
440 if (IntersectingChild != ParentRI.Children.end()) {
441 ++NumErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000442 error() << "DIEs have overlapping address ranges:";
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000443 dump(Die);
444 dump(IntersectingChild->Die) << '\n';
Jonas Devlieghere58910602017-09-14 11:33:42 +0000445 }
446
447 // Verify that ranges are contained within their parent.
448 bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() &&
449 !(Die.getTag() == DW_TAG_subprogram &&
450 ParentRI.Die.getTag() == DW_TAG_subprogram);
451 if (ShouldBeContained && !ParentRI.contains(RI)) {
452 ++NumErrors;
Jonas Devlieghere63eca152018-05-22 17:38:03 +0000453 error() << "DIE address ranges are not contained in its parent's ranges:";
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000454 dump(ParentRI.Die);
455 dump(Die, 2) << '\n';
Jonas Devlieghere58910602017-09-14 11:33:42 +0000456 }
457
458 // Recursively check children.
459 for (DWARFDie Child : Die)
460 NumErrors += verifyDieRanges(Child, RI);
461
Spyridoula Gravanie0ba4152017-07-24 21:04:11 +0000462 return NumErrors;
463}
464
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000465unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
466 DWARFAttribute &AttrValue) {
467 unsigned NumErrors = 0;
George Rimar144e4c52017-10-27 10:42:04 +0000468 auto ReportError = [&](const Twine &TitleMsg) {
469 ++NumErrors;
470 error() << TitleMsg << '\n';
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000471 dump(Die) << '\n';
George Rimar144e4c52017-10-27 10:42:04 +0000472 };
473
474 const DWARFObject &DObj = DCtx.getDWARFObj();
Greg Claytonc5b2d562017-05-03 18:25:46 +0000475 const auto Attr = AttrValue.Attr;
476 switch (Attr) {
477 case DW_AT_ranges:
478 // Make sure the offset in the DW_AT_ranges attribute is valid.
479 if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
George Rimar144e4c52017-10-27 10:42:04 +0000480 if (*SectionOffset >= DObj.getRangeSection().Data.size())
481 ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:");
482 break;
Greg Claytonc5b2d562017-05-03 18:25:46 +0000483 }
George Rimar144e4c52017-10-27 10:42:04 +0000484 ReportError("DIE has invalid DW_AT_ranges encoding:");
Greg Claytonc5b2d562017-05-03 18:25:46 +0000485 break;
486 case DW_AT_stmt_list:
487 // Make sure the offset in the DW_AT_stmt_list attribute is valid.
488 if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
George Rimar144e4c52017-10-27 10:42:04 +0000489 if (*SectionOffset >= DObj.getLineSection().Data.size())
490 ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " +
George Rimar3d07f602017-10-27 10:58:04 +0000491 llvm::formatv("{0:x8}", *SectionOffset));
George Rimar144e4c52017-10-27 10:42:04 +0000492 break;
Greg Claytonc5b2d562017-05-03 18:25:46 +0000493 }
George Rimar144e4c52017-10-27 10:42:04 +0000494 ReportError("DIE has invalid DW_AT_stmt_list encoding:");
Greg Claytonc5b2d562017-05-03 18:25:46 +0000495 break;
George Rimar144e4c52017-10-27 10:42:04 +0000496 case DW_AT_location: {
Jonas Devlieghere7e0b0232018-05-22 17:37:27 +0000497 auto VerifyLocationExpr = [&](StringRef D) {
Jonas Devlieghere7d4a9742018-02-17 13:06:37 +0000498 DWARFUnit *U = Die.getDwarfUnit();
499 DataExtractor Data(D, DCtx.isLittleEndian(), 0);
500 DWARFExpression Expression(Data, U->getVersion(),
501 U->getAddressByteSize());
502 bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
503 return Op.isError();
504 });
505 if (Error)
506 ReportError("DIE contains invalid DWARF expression:");
507 };
508 if (Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock()) {
509 // Verify inlined location.
Jonas Devlieghere7e0b0232018-05-22 17:37:27 +0000510 VerifyLocationExpr(llvm::toStringRef(*Expr));
511 } else if (auto LocOffset = AttrValue.Value.getAsSectionOffset()) {
Jonas Devlieghere7d4a9742018-02-17 13:06:37 +0000512 // Verify location list.
513 if (auto DebugLoc = DCtx.getDebugLoc())
514 if (auto LocList = DebugLoc->getLocationListAtOffset(*LocOffset))
515 for (const auto &Entry : LocList->Entries)
Jonas Devlieghere7e0b0232018-05-22 17:37:27 +0000516 VerifyLocationExpr({Entry.Loc.data(), Entry.Loc.size()});
George Rimar144e4c52017-10-27 10:42:04 +0000517 }
George Rimar144e4c52017-10-27 10:42:04 +0000518 break;
519 }
Jonas Devlieghere7ef2c202018-09-21 07:49:29 +0000520 case DW_AT_specification:
521 case DW_AT_abstract_origin: {
522 if (auto ReferencedDie = Die.getAttributeValueAsReferencedDie(Attr)) {
523 auto DieTag = Die.getTag();
524 auto RefTag = ReferencedDie.getTag();
525 if (DieTag == RefTag)
526 break;
527 if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram)
528 break;
529 if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member)
530 break;
531 ReportError("DIE with tag " + TagString(DieTag) + " has " +
532 AttributeString(Attr) +
533 " that points to DIE with "
534 "incompatible tag " +
535 TagString(RefTag));
536 }
David Bolvansky7e30c912018-10-10 20:10:37 +0000537 break;
Jonas Devlieghere7ef2c202018-09-21 07:49:29 +0000538 }
Jonas Devlieghereb3227422018-09-21 07:50:21 +0000539 case DW_AT_type: {
540 DWARFDie TypeDie = Die.getAttributeValueAsReferencedDie(DW_AT_type);
541 if (TypeDie && !isType(TypeDie.getTag())) {
542 ReportError("DIE has " + AttributeString(Attr) +
543 " with incompatible tag " + TagString(TypeDie.getTag()));
Jonas Devlieghereb3227422018-09-21 07:50:21 +0000544 }
David Bolvansky7e30c912018-10-10 20:10:37 +0000545 break;
Jonas Devlieghereb3227422018-09-21 07:50:21 +0000546 }
Greg Claytonc5b2d562017-05-03 18:25:46 +0000547 default:
548 break;
549 }
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000550 return NumErrors;
Greg Claytonc5b2d562017-05-03 18:25:46 +0000551}
Greg Claytonb8c162b2017-05-03 16:02:29 +0000552
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000553unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
554 DWARFAttribute &AttrValue) {
Rafael Espindolac398e672017-07-19 22:27:28 +0000555 const DWARFObject &DObj = DCtx.getDWARFObj();
Paul Robinson746c22382018-11-07 21:39:09 +0000556 auto DieCU = Die.getDwarfUnit();
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000557 unsigned NumErrors = 0;
Greg Claytonc5b2d562017-05-03 18:25:46 +0000558 const auto Form = AttrValue.Value.getForm();
559 switch (Form) {
560 case DW_FORM_ref1:
561 case DW_FORM_ref2:
562 case DW_FORM_ref4:
563 case DW_FORM_ref8:
564 case DW_FORM_ref_udata: {
565 // Verify all CU relative references are valid CU offsets.
566 Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
567 assert(RefVal);
568 if (RefVal) {
Greg Claytonc5b2d562017-05-03 18:25:46 +0000569 auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
570 auto CUOffset = AttrValue.Value.getRawUValue();
571 if (CUOffset >= CUSize) {
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000572 ++NumErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000573 error() << FormEncodingString(Form) << " CU offset "
574 << format("0x%08" PRIx64, CUOffset)
575 << " is invalid (must be less than CU size of "
576 << format("0x%08" PRIx32, CUSize) << "):\n";
Adrian Prantld3f9f212017-09-20 17:44:00 +0000577 Die.dump(OS, 0, DumpOpts);
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000578 dump(Die) << '\n';
Greg Claytonc5b2d562017-05-03 18:25:46 +0000579 } else {
580 // Valid reference, but we will verify it points to an actual
581 // DIE later.
582 ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
Greg Claytonb8c162b2017-05-03 16:02:29 +0000583 }
584 }
Greg Claytonc5b2d562017-05-03 18:25:46 +0000585 break;
Greg Claytonb8c162b2017-05-03 16:02:29 +0000586 }
Greg Claytonc5b2d562017-05-03 18:25:46 +0000587 case DW_FORM_ref_addr: {
588 // Verify all absolute DIE references have valid offsets in the
589 // .debug_info section.
590 Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
591 assert(RefVal);
592 if (RefVal) {
Paul Robinson746c22382018-11-07 21:39:09 +0000593 if (*RefVal >= DieCU->getInfoSection().Data.size()) {
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000594 ++NumErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000595 error() << "DW_FORM_ref_addr offset beyond .debug_info "
596 "bounds:\n";
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000597 dump(Die) << '\n';
Greg Claytonc5b2d562017-05-03 18:25:46 +0000598 } else {
599 // Valid reference, but we will verify it points to an actual
600 // DIE later.
601 ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
602 }
603 }
604 break;
605 }
606 case DW_FORM_strp: {
607 auto SecOffset = AttrValue.Value.getAsSectionOffset();
608 assert(SecOffset); // DW_FORM_strp is a section offset.
Rafael Espindolac398e672017-07-19 22:27:28 +0000609 if (SecOffset && *SecOffset >= DObj.getStringSection().size()) {
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000610 ++NumErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000611 error() << "DW_FORM_strp offset beyond .debug_str bounds:\n";
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000612 dump(Die) << '\n';
Greg Claytonc5b2d562017-05-03 18:25:46 +0000613 }
614 break;
615 }
Wolfgang Pieb5253ccc2018-11-03 00:27:35 +0000616 case DW_FORM_strx:
617 case DW_FORM_strx1:
618 case DW_FORM_strx2:
619 case DW_FORM_strx3:
620 case DW_FORM_strx4: {
621 auto Index = AttrValue.Value.getRawUValue();
622 auto DieCU = Die.getDwarfUnit();
623 // Check that we have a valid DWARF v5 string offsets table.
624 if (!DieCU->getStringOffsetsTableContribution()) {
625 ++NumErrors;
626 error() << FormEncodingString(Form)
627 << " used without a valid string offsets table:\n";
628 dump(Die) << '\n';
629 break;
630 }
631 // Check that the index is within the bounds of the section.
632 unsigned ItemSize = DieCU->getDwarfStringOffsetsByteSize();
633 // Use a 64-bit type to calculate the offset to guard against overflow.
634 uint64_t Offset =
635 (uint64_t)DieCU->getStringOffsetsBase() + Index * ItemSize;
636 if (DObj.getStringOffsetSection().Data.size() < Offset + ItemSize) {
637 ++NumErrors;
638 error() << FormEncodingString(Form) << " uses index "
639 << format("%" PRIu64, Index) << ", which is too large:\n";
640 dump(Die) << '\n';
641 break;
642 }
643 // Check that the string offset is valid.
644 uint64_t StringOffset = *DieCU->getStringOffsetSectionItem(Index);
645 if (StringOffset >= DObj.getStringSection().size()) {
646 ++NumErrors;
647 error() << FormEncodingString(Form) << " uses index "
648 << format("%" PRIu64, Index)
649 << ", but the referenced string"
650 " offset is beyond .debug_str bounds:\n";
651 dump(Die) << '\n';
652 }
653 break;
654 }
Greg Claytonc5b2d562017-05-03 18:25:46 +0000655 default:
656 break;
657 }
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000658 return NumErrors;
Greg Claytonc5b2d562017-05-03 18:25:46 +0000659}
Greg Claytonb8c162b2017-05-03 16:02:29 +0000660
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000661unsigned DWARFVerifier::verifyDebugInfoReferences() {
Greg Claytonb8c162b2017-05-03 16:02:29 +0000662 // Take all references and make sure they point to an actual DIE by
663 // getting the DIE by offset and emitting an error
664 OS << "Verifying .debug_info references...\n";
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000665 unsigned NumErrors = 0;
Greg Claytonb8c162b2017-05-03 16:02:29 +0000666 for (auto Pair : ReferenceToDIEOffsets) {
667 auto Die = DCtx.getDIEForOffset(Pair.first);
668 if (Die)
669 continue;
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000670 ++NumErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000671 error() << "invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
672 << ". Offset is in between DIEs:\n";
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000673 for (auto Offset : Pair.second)
674 dump(DCtx.getDIEForOffset(Offset)) << '\n';
Greg Claytonb8c162b2017-05-03 16:02:29 +0000675 OS << "\n";
676 }
Spyridoula Gravanif6bd788d2017-07-18 01:00:26 +0000677 return NumErrors;
Greg Claytonb8c162b2017-05-03 16:02:29 +0000678}
679
Greg Claytonc5b2d562017-05-03 18:25:46 +0000680void DWARFVerifier::verifyDebugLineStmtOffsets() {
Greg Claytonb8c162b2017-05-03 16:02:29 +0000681 std::map<uint64_t, DWARFDie> StmtListToDie;
Greg Claytonb8c162b2017-05-03 16:02:29 +0000682 for (const auto &CU : DCtx.compile_units()) {
Greg Claytonc5b2d562017-05-03 18:25:46 +0000683 auto Die = CU->getUnitDIE();
Greg Claytonb8c162b2017-05-03 16:02:29 +0000684 // Get the attribute value as a section offset. No need to produce an
685 // error here if the encoding isn't correct because we validate this in
686 // the .debug_info verifier.
Greg Claytonc5b2d562017-05-03 18:25:46 +0000687 auto StmtSectionOffset = toSectionOffset(Die.find(DW_AT_stmt_list));
Greg Claytonb8c162b2017-05-03 16:02:29 +0000688 if (!StmtSectionOffset)
689 continue;
690 const uint32_t LineTableOffset = *StmtSectionOffset;
Greg Claytonc5b2d562017-05-03 18:25:46 +0000691 auto LineTable = DCtx.getLineTableForUnit(CU.get());
Rafael Espindolac398e672017-07-19 22:27:28 +0000692 if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
Greg Claytonc5b2d562017-05-03 18:25:46 +0000693 if (!LineTable) {
694 ++NumDebugLineErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000695 error() << ".debug_line[" << format("0x%08" PRIx32, LineTableOffset)
696 << "] was not able to be parsed for CU:\n";
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000697 dump(Die) << '\n';
Greg Claytonc5b2d562017-05-03 18:25:46 +0000698 continue;
699 }
700 } else {
701 // Make sure we don't get a valid line table back if the offset is wrong.
702 assert(LineTable == nullptr);
Greg Claytonb8c162b2017-05-03 16:02:29 +0000703 // Skip this line table as it isn't valid. No need to create an error
704 // here because we validate this in the .debug_info verifier.
705 continue;
706 }
Greg Claytonb8c162b2017-05-03 16:02:29 +0000707 auto Iter = StmtListToDie.find(LineTableOffset);
708 if (Iter != StmtListToDie.end()) {
709 ++NumDebugLineErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000710 error() << "two compile unit DIEs, "
711 << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
712 << format("0x%08" PRIx32, Die.getOffset())
713 << ", have the same DW_AT_stmt_list section offset:\n";
Jonas Devliegheref1f3e732018-09-19 08:08:13 +0000714 dump(Iter->second);
715 dump(Die) << '\n';
Greg Claytonb8c162b2017-05-03 16:02:29 +0000716 // Already verified this line table before, no need to do it again.
717 continue;
718 }
Greg Claytonc5b2d562017-05-03 18:25:46 +0000719 StmtListToDie[LineTableOffset] = Die;
720 }
721}
Greg Claytonb8c162b2017-05-03 16:02:29 +0000722
Greg Claytonc5b2d562017-05-03 18:25:46 +0000723void DWARFVerifier::verifyDebugLineRows() {
724 for (const auto &CU : DCtx.compile_units()) {
725 auto Die = CU->getUnitDIE();
Greg Claytonb8c162b2017-05-03 16:02:29 +0000726 auto LineTable = DCtx.getLineTableForUnit(CU.get());
Greg Claytonc5b2d562017-05-03 18:25:46 +0000727 // If there is no line table we will have created an error in the
728 // .debug_info verifier or in verifyDebugLineStmtOffsets().
729 if (!LineTable)
Greg Claytonb8c162b2017-05-03 16:02:29 +0000730 continue;
Jonas Devliegheref4ed65d2017-09-08 09:48:51 +0000731
732 // Verify prologue.
Greg Claytonb8c162b2017-05-03 16:02:29 +0000733 uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
Jonas Devliegheref4ed65d2017-09-08 09:48:51 +0000734 uint32_t MaxDirIndex = LineTable->Prologue.IncludeDirectories.size();
735 uint32_t FileIndex = 1;
736 StringMap<uint16_t> FullPathMap;
737 for (const auto &FileName : LineTable->Prologue.FileNames) {
738 // Verify directory index.
739 if (FileName.DirIdx > MaxDirIndex) {
740 ++NumDebugLineErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000741 error() << ".debug_line["
742 << format("0x%08" PRIx64,
743 *toSectionOffset(Die.find(DW_AT_stmt_list)))
744 << "].prologue.file_names[" << FileIndex
745 << "].dir_idx contains an invalid index: " << FileName.DirIdx
746 << "\n";
Jonas Devliegheref4ed65d2017-09-08 09:48:51 +0000747 }
748
749 // Check file paths for duplicates.
750 std::string FullPath;
751 const bool HasFullPath = LineTable->getFileNameByIndex(
752 FileIndex, CU->getCompilationDir(),
753 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FullPath);
754 assert(HasFullPath && "Invalid index?");
755 (void)HasFullPath;
756 auto It = FullPathMap.find(FullPath);
757 if (It == FullPathMap.end())
758 FullPathMap[FullPath] = FileIndex;
759 else if (It->second != FileIndex) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000760 warn() << ".debug_line["
761 << format("0x%08" PRIx64,
762 *toSectionOffset(Die.find(DW_AT_stmt_list)))
763 << "].prologue.file_names[" << FileIndex
764 << "] is a duplicate of file_names[" << It->second << "]\n";
Jonas Devliegheref4ed65d2017-09-08 09:48:51 +0000765 }
766
767 FileIndex++;
768 }
769
770 // Verify rows.
Greg Claytonb8c162b2017-05-03 16:02:29 +0000771 uint64_t PrevAddress = 0;
772 uint32_t RowIndex = 0;
773 for (const auto &Row : LineTable->Rows) {
Jonas Devliegheref4ed65d2017-09-08 09:48:51 +0000774 // Verify row address.
Greg Claytonb8c162b2017-05-03 16:02:29 +0000775 if (Row.Address < PrevAddress) {
776 ++NumDebugLineErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000777 error() << ".debug_line["
778 << format("0x%08" PRIx64,
779 *toSectionOffset(Die.find(DW_AT_stmt_list)))
780 << "] row[" << RowIndex
781 << "] decreases in address from previous row:\n";
Greg Claytonb8c162b2017-05-03 16:02:29 +0000782
783 DWARFDebugLine::Row::dumpTableHeader(OS);
784 if (RowIndex > 0)
785 LineTable->Rows[RowIndex - 1].dump(OS);
786 Row.dump(OS);
787 OS << '\n';
788 }
789
Jonas Devliegheref4ed65d2017-09-08 09:48:51 +0000790 // Verify file index.
Greg Claytonb8c162b2017-05-03 16:02:29 +0000791 if (Row.File > MaxFileIndex) {
792 ++NumDebugLineErrors;
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000793 error() << ".debug_line["
794 << format("0x%08" PRIx64,
795 *toSectionOffset(Die.find(DW_AT_stmt_list)))
796 << "][" << RowIndex << "] has invalid file index " << Row.File
797 << " (valid values are [1," << MaxFileIndex << "]):\n";
Greg Claytonb8c162b2017-05-03 16:02:29 +0000798 DWARFDebugLine::Row::dumpTableHeader(OS);
799 Row.dump(OS);
800 OS << '\n';
801 }
802 if (Row.EndSequence)
803 PrevAddress = 0;
804 else
805 PrevAddress = Row.Address;
806 ++RowIndex;
807 }
808 }
Greg Claytonc5b2d562017-05-03 18:25:46 +0000809}
810
Saleem Abdulrasoolec77a652018-10-28 22:30:48 +0000811DWARFVerifier::DWARFVerifier(raw_ostream &S, DWARFContext &D,
812 DIDumpOptions DumpOpts)
813 : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)), IsObjectFile(false),
814 IsMachOObject(false) {
815 if (const auto *F = DCtx.getDWARFObj().getFile()) {
816 IsObjectFile = F->isRelocatableObject();
817 IsMachOObject = F->isMachO();
818 }
819}
820
Greg Claytonc5b2d562017-05-03 18:25:46 +0000821bool DWARFVerifier::handleDebugLine() {
822 NumDebugLineErrors = 0;
823 OS << "Verifying .debug_line...\n";
824 verifyDebugLineStmtOffsets();
825 verifyDebugLineRows();
Greg Claytonb8c162b2017-05-03 16:02:29 +0000826 return NumDebugLineErrors == 0;
827}
Spyridoula Gravanie41823b2017-06-14 00:17:55 +0000828
Pavel Labath9b36fd22018-01-22 13:17:23 +0000829unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
830 DataExtractor *StrData,
831 const char *SectionName) {
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000832 unsigned NumErrors = 0;
833 DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), *AccelSection,
834 DCtx.isLittleEndian(), 0);
Pavel Labath9b36fd22018-01-22 13:17:23 +0000835 AppleAcceleratorTable AccelTable(AccelSectionData, *StrData);
Spyridoula Gravanie41823b2017-06-14 00:17:55 +0000836
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000837 OS << "Verifying " << SectionName << "...\n";
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000838
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000839 // Verify that the fixed part of the header is not too short.
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000840 if (!AccelSectionData.isValidOffset(AccelTable.getSizeHdr())) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000841 error() << "Section is too small to fit a section header.\n";
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000842 return 1;
Spyridoula Gravanie41823b2017-06-14 00:17:55 +0000843 }
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000844
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000845 // Verify that the section is not too short.
Jonas Devlieghereba915892017-12-11 18:22:47 +0000846 if (Error E = AccelTable.extract()) {
847 error() << toString(std::move(E)) << '\n';
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000848 return 1;
849 }
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000850
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000851 // Verify that all buckets have a valid hash index or are empty.
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000852 uint32_t NumBuckets = AccelTable.getNumBuckets();
853 uint32_t NumHashes = AccelTable.getNumHashes();
Spyridoula Gravanie41823b2017-06-14 00:17:55 +0000854
855 uint32_t BucketsOffset =
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000856 AccelTable.getSizeHdr() + AccelTable.getHeaderDataLength();
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000857 uint32_t HashesBase = BucketsOffset + NumBuckets * 4;
858 uint32_t OffsetsBase = HashesBase + NumHashes * 4;
Spyridoula Gravanie41823b2017-06-14 00:17:55 +0000859 for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000860 uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
Spyridoula Gravanie41823b2017-06-14 00:17:55 +0000861 if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000862 error() << format("Bucket[%d] has invalid hash index: %u.\n", BucketIdx,
863 HashIdx);
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000864 ++NumErrors;
Spyridoula Gravanie41823b2017-06-14 00:17:55 +0000865 }
866 }
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000867 uint32_t NumAtoms = AccelTable.getAtomsDesc().size();
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000868 if (NumAtoms == 0) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000869 error() << "No atoms: failed to read HashData.\n";
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000870 return 1;
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000871 }
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000872 if (!AccelTable.validateForms()) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000873 error() << "Unsupported form: failed to read HashData.\n";
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000874 return 1;
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000875 }
876
877 for (uint32_t HashIdx = 0; HashIdx < NumHashes; ++HashIdx) {
878 uint32_t HashOffset = HashesBase + 4 * HashIdx;
879 uint32_t DataOffset = OffsetsBase + 4 * HashIdx;
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000880 uint32_t Hash = AccelSectionData.getU32(&HashOffset);
881 uint32_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
882 if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
883 sizeof(uint64_t))) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000884 error() << format("Hash[%d] has invalid HashData offset: 0x%08x.\n",
885 HashIdx, HashDataOffset);
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000886 ++NumErrors;
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000887 }
888
889 uint32_t StrpOffset;
890 uint32_t StringOffset;
891 uint32_t StringCount = 0;
Spyridoula Gravani70d35e12017-07-31 18:01:16 +0000892 unsigned Offset;
893 unsigned Tag;
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000894 while ((StrpOffset = AccelSectionData.getU32(&HashDataOffset)) != 0) {
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000895 const uint32_t NumHashDataObjects =
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000896 AccelSectionData.getU32(&HashDataOffset);
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000897 for (uint32_t HashDataIdx = 0; HashDataIdx < NumHashDataObjects;
898 ++HashDataIdx) {
Spyridoula Gravani70d35e12017-07-31 18:01:16 +0000899 std::tie(Offset, Tag) = AccelTable.readAtoms(HashDataOffset);
900 auto Die = DCtx.getDIEForOffset(Offset);
901 if (!Die) {
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000902 const uint32_t BucketIdx =
903 NumBuckets ? (Hash % NumBuckets) : UINT32_MAX;
904 StringOffset = StrpOffset;
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000905 const char *Name = StrData->getCStr(&StringOffset);
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000906 if (!Name)
907 Name = "<NULL>";
908
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000909 error() << format(
910 "%s Bucket[%d] Hash[%d] = 0x%08x "
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000911 "Str[%u] = 0x%08x "
912 "DIE[%d] = 0x%08x is not a valid DIE offset for \"%s\".\n",
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000913 SectionName, BucketIdx, HashIdx, Hash, StringCount, StrpOffset,
Spyridoula Gravani70d35e12017-07-31 18:01:16 +0000914 HashDataIdx, Offset, Name);
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000915
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000916 ++NumErrors;
Spyridoula Gravani70d35e12017-07-31 18:01:16 +0000917 continue;
918 }
919 if ((Tag != dwarf::DW_TAG_null) && (Die.getTag() != Tag)) {
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +0000920 error() << "Tag " << dwarf::TagString(Tag)
921 << " in accelerator table does not match Tag "
922 << dwarf::TagString(Die.getTag()) << " of DIE[" << HashDataIdx
923 << "].\n";
Spyridoula Gravani70d35e12017-07-31 18:01:16 +0000924 ++NumErrors;
Spyridoula Gravani837c1102017-06-29 20:13:05 +0000925 }
926 }
927 ++StringCount;
928 }
929 }
Spyridoula Gravanidc635f42017-07-26 00:52:31 +0000930 return NumErrors;
931}
932
Pavel Labathb136c392018-03-08 15:34:42 +0000933unsigned
934DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) {
935 // A map from CU offset to the (first) Name Index offset which claims to index
936 // this CU.
937 DenseMap<uint32_t, uint32_t> CUMap;
938 const uint32_t NotIndexed = std::numeric_limits<uint32_t>::max();
939
940 CUMap.reserve(DCtx.getNumCompileUnits());
941 for (const auto &CU : DCtx.compile_units())
942 CUMap[CU->getOffset()] = NotIndexed;
943
944 unsigned NumErrors = 0;
945 for (const DWARFDebugNames::NameIndex &NI : AccelTable) {
946 if (NI.getCUCount() == 0) {
947 error() << formatv("Name Index @ {0:x} does not index any CU\n",
948 NI.getUnitOffset());
949 ++NumErrors;
950 continue;
951 }
952 for (uint32_t CU = 0, End = NI.getCUCount(); CU < End; ++CU) {
953 uint32_t Offset = NI.getCUOffset(CU);
954 auto Iter = CUMap.find(Offset);
955
956 if (Iter == CUMap.end()) {
957 error() << formatv(
958 "Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
959 NI.getUnitOffset(), Offset);
960 ++NumErrors;
961 continue;
962 }
963
964 if (Iter->second != NotIndexed) {
965 error() << formatv("Name Index @ {0:x} references a CU @ {1:x}, but "
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +0000966 "this CU is already indexed by Name Index @ {2:x}\n",
967 NI.getUnitOffset(), Offset, Iter->second);
Pavel Labathb136c392018-03-08 15:34:42 +0000968 continue;
969 }
970 Iter->second = NI.getUnitOffset();
971 }
972 }
973
974 for (const auto &KV : CUMap) {
975 if (KV.second == NotIndexed)
976 warn() << formatv("CU @ {0:x} not covered by any Name Index\n", KV.first);
977 }
978
979 return NumErrors;
980}
981
Pavel Labath906b7772018-03-16 10:02:16 +0000982unsigned
983DWARFVerifier::verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
984 const DataExtractor &StrData) {
985 struct BucketInfo {
986 uint32_t Bucket;
987 uint32_t Index;
988
989 constexpr BucketInfo(uint32_t Bucket, uint32_t Index)
990 : Bucket(Bucket), Index(Index) {}
991 bool operator<(const BucketInfo &RHS) const { return Index < RHS.Index; };
992 };
993
994 uint32_t NumErrors = 0;
995 if (NI.getBucketCount() == 0) {
996 warn() << formatv("Name Index @ {0:x} does not contain a hash table.\n",
997 NI.getUnitOffset());
998 return NumErrors;
999 }
1000
1001 // Build up a list of (Bucket, Index) pairs. We use this later to verify that
1002 // each Name is reachable from the appropriate bucket.
1003 std::vector<BucketInfo> BucketStarts;
1004 BucketStarts.reserve(NI.getBucketCount() + 1);
1005 for (uint32_t Bucket = 0, End = NI.getBucketCount(); Bucket < End; ++Bucket) {
1006 uint32_t Index = NI.getBucketArrayEntry(Bucket);
1007 if (Index > NI.getNameCount()) {
1008 error() << formatv("Bucket {0} of Name Index @ {1:x} contains invalid "
1009 "value {2}. Valid range is [0, {3}].\n",
1010 Bucket, NI.getUnitOffset(), Index, NI.getNameCount());
1011 ++NumErrors;
1012 continue;
1013 }
1014 if (Index > 0)
1015 BucketStarts.emplace_back(Bucket, Index);
1016 }
1017
1018 // If there were any buckets with invalid values, skip further checks as they
1019 // will likely produce many errors which will only confuse the actual root
1020 // problem.
1021 if (NumErrors > 0)
1022 return NumErrors;
1023
1024 // Sort the list in the order of increasing "Index" entries.
1025 array_pod_sort(BucketStarts.begin(), BucketStarts.end());
1026
1027 // Insert a sentinel entry at the end, so we can check that the end of the
1028 // table is covered in the loop below.
1029 BucketStarts.emplace_back(NI.getBucketCount(), NI.getNameCount() + 1);
1030
1031 // Loop invariant: NextUncovered is the (1-based) index of the first Name
1032 // which is not reachable by any of the buckets we processed so far (and
1033 // hasn't been reported as uncovered).
1034 uint32_t NextUncovered = 1;
1035 for (const BucketInfo &B : BucketStarts) {
1036 // Under normal circumstances B.Index be equal to NextUncovered, but it can
1037 // be less if a bucket points to names which are already known to be in some
1038 // bucket we processed earlier. In that case, we won't trigger this error,
1039 // but report the mismatched hash value error instead. (We know the hash
1040 // will not match because we have already verified that the name's hash
1041 // puts it into the previous bucket.)
1042 if (B.Index > NextUncovered) {
1043 error() << formatv("Name Index @ {0:x}: Name table entries [{1}, {2}] "
1044 "are not covered by the hash table.\n",
1045 NI.getUnitOffset(), NextUncovered, B.Index - 1);
1046 ++NumErrors;
1047 }
1048 uint32_t Idx = B.Index;
1049
1050 // The rest of the checks apply only to non-sentinel entries.
1051 if (B.Bucket == NI.getBucketCount())
1052 break;
1053
1054 // This triggers if a non-empty bucket points to a name with a mismatched
1055 // hash. Clients are likely to interpret this as an empty bucket, because a
1056 // mismatched hash signals the end of a bucket, but if this is indeed an
1057 // empty bucket, the producer should have signalled this by marking the
1058 // bucket as empty.
1059 uint32_t FirstHash = NI.getHashArrayEntry(Idx);
1060 if (FirstHash % NI.getBucketCount() != B.Bucket) {
1061 error() << formatv(
1062 "Name Index @ {0:x}: Bucket {1} is not empty but points to a "
1063 "mismatched hash value {2:x} (belonging to bucket {3}).\n",
1064 NI.getUnitOffset(), B.Bucket, FirstHash,
1065 FirstHash % NI.getBucketCount());
1066 ++NumErrors;
1067 }
1068
1069 // This find the end of this bucket and also verifies that all the hashes in
1070 // this bucket are correct by comparing the stored hashes to the ones we
1071 // compute ourselves.
1072 while (Idx <= NI.getNameCount()) {
1073 uint32_t Hash = NI.getHashArrayEntry(Idx);
1074 if (Hash % NI.getBucketCount() != B.Bucket)
1075 break;
1076
Pavel Labathd6ca0632018-06-01 10:33:11 +00001077 const char *Str = NI.getNameTableEntry(Idx).getString();
Pavel Labath906b7772018-03-16 10:02:16 +00001078 if (caseFoldingDjbHash(Str) != Hash) {
1079 error() << formatv("Name Index @ {0:x}: String ({1}) at index {2} "
1080 "hashes to {3:x}, but "
1081 "the Name Index hash is {4:x}\n",
1082 NI.getUnitOffset(), Str, Idx,
1083 caseFoldingDjbHash(Str), Hash);
1084 ++NumErrors;
1085 }
1086
1087 ++Idx;
1088 }
1089 NextUncovered = std::max(NextUncovered, Idx);
1090 }
1091 return NumErrors;
1092}
1093
Pavel Labath79cd9422018-03-22 14:50:44 +00001094unsigned DWARFVerifier::verifyNameIndexAttribute(
1095 const DWARFDebugNames::NameIndex &NI, const DWARFDebugNames::Abbrev &Abbr,
1096 DWARFDebugNames::AttributeEncoding AttrEnc) {
1097 StringRef FormName = dwarf::FormEncodingString(AttrEnc.Form);
1098 if (FormName.empty()) {
1099 error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1100 "unknown form: {3}.\n",
1101 NI.getUnitOffset(), Abbr.Code, AttrEnc.Index,
1102 AttrEnc.Form);
1103 return 1;
1104 }
1105
1106 if (AttrEnc.Index == DW_IDX_type_hash) {
1107 if (AttrEnc.Form != dwarf::DW_FORM_data8) {
1108 error() << formatv(
1109 "NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_type_hash "
1110 "uses an unexpected form {2} (should be {3}).\n",
1111 NI.getUnitOffset(), Abbr.Code, AttrEnc.Form, dwarf::DW_FORM_data8);
1112 return 1;
1113 }
1114 }
1115
1116 // A list of known index attributes and their expected form classes.
1117 // DW_IDX_type_hash is handled specially in the check above, as it has a
1118 // specific form (not just a form class) we should expect.
1119 struct FormClassTable {
1120 dwarf::Index Index;
1121 DWARFFormValue::FormClass Class;
1122 StringLiteral ClassName;
1123 };
1124 static constexpr FormClassTable Table[] = {
1125 {dwarf::DW_IDX_compile_unit, DWARFFormValue::FC_Constant, {"constant"}},
1126 {dwarf::DW_IDX_type_unit, DWARFFormValue::FC_Constant, {"constant"}},
1127 {dwarf::DW_IDX_die_offset, DWARFFormValue::FC_Reference, {"reference"}},
1128 {dwarf::DW_IDX_parent, DWARFFormValue::FC_Constant, {"constant"}},
1129 };
1130
1131 ArrayRef<FormClassTable> TableRef(Table);
1132 auto Iter = find_if(TableRef, [AttrEnc](const FormClassTable &T) {
1133 return T.Index == AttrEnc.Index;
1134 });
1135 if (Iter == TableRef.end()) {
1136 warn() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} contains an "
1137 "unknown index attribute: {2}.\n",
1138 NI.getUnitOffset(), Abbr.Code, AttrEnc.Index);
1139 return 0;
1140 }
1141
1142 if (!DWARFFormValue(AttrEnc.Form).isFormClass(Iter->Class)) {
1143 error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x}: {2} uses an "
1144 "unexpected form {3} (expected form class {4}).\n",
1145 NI.getUnitOffset(), Abbr.Code, AttrEnc.Index,
1146 AttrEnc.Form, Iter->ClassName);
1147 return 1;
1148 }
1149 return 0;
1150}
1151
1152unsigned
1153DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) {
Pavel Labathc9f07b02018-04-06 13:34:12 +00001154 if (NI.getLocalTUCount() + NI.getForeignTUCount() > 0) {
1155 warn() << formatv("Name Index @ {0:x}: Verifying indexes of type units is "
1156 "not currently supported.\n",
1157 NI.getUnitOffset());
1158 return 0;
1159 }
1160
Pavel Labath79cd9422018-03-22 14:50:44 +00001161 unsigned NumErrors = 0;
1162 for (const auto &Abbrev : NI.getAbbrevs()) {
1163 StringRef TagName = dwarf::TagString(Abbrev.Tag);
1164 if (TagName.empty()) {
1165 warn() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} references an "
1166 "unknown tag: {2}.\n",
1167 NI.getUnitOffset(), Abbrev.Code, Abbrev.Tag);
1168 }
1169 SmallSet<unsigned, 5> Attributes;
1170 for (const auto &AttrEnc : Abbrev.Attributes) {
1171 if (!Attributes.insert(AttrEnc.Index).second) {
1172 error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x} contains "
1173 "multiple {2} attributes.\n",
1174 NI.getUnitOffset(), Abbrev.Code, AttrEnc.Index);
1175 ++NumErrors;
1176 continue;
1177 }
1178 NumErrors += verifyNameIndexAttribute(NI, Abbrev, AttrEnc);
1179 }
Pavel Labathc9f07b02018-04-06 13:34:12 +00001180
1181 if (NI.getCUCount() > 1 && !Attributes.count(dwarf::DW_IDX_compile_unit)) {
1182 error() << formatv("NameIndex @ {0:x}: Indexing multiple compile units "
1183 "and abbreviation {1:x} has no {2} attribute.\n",
1184 NI.getUnitOffset(), Abbrev.Code,
1185 dwarf::DW_IDX_compile_unit);
1186 ++NumErrors;
1187 }
1188 if (!Attributes.count(dwarf::DW_IDX_die_offset)) {
1189 error() << formatv(
1190 "NameIndex @ {0:x}: Abbreviation {1:x} has no {2} attribute.\n",
1191 NI.getUnitOffset(), Abbrev.Code, dwarf::DW_IDX_die_offset);
1192 ++NumErrors;
1193 }
Pavel Labath79cd9422018-03-22 14:50:44 +00001194 }
1195 return NumErrors;
1196}
1197
Jonas Devlieghere6e5c7e62018-09-03 12:12:17 +00001198static SmallVector<StringRef, 2> getNames(const DWARFDie &DIE,
1199 bool IncludeLinkageName = true) {
Pavel Labathc9f07b02018-04-06 13:34:12 +00001200 SmallVector<StringRef, 2> Result;
1201 if (const char *Str = DIE.getName(DINameKind::ShortName))
1202 Result.emplace_back(Str);
1203 else if (DIE.getTag() == dwarf::DW_TAG_namespace)
1204 Result.emplace_back("(anonymous namespace)");
1205
Jonas Devlieghere6e5c7e62018-09-03 12:12:17 +00001206 if (IncludeLinkageName) {
1207 if (const char *Str = DIE.getName(DINameKind::LinkageName)) {
1208 if (Result.empty() || Result[0] != Str)
1209 Result.emplace_back(Str);
1210 }
Pavel Labathc9f07b02018-04-06 13:34:12 +00001211 }
1212
1213 return Result;
1214}
1215
Pavel Labathd6ca0632018-06-01 10:33:11 +00001216unsigned DWARFVerifier::verifyNameIndexEntries(
1217 const DWARFDebugNames::NameIndex &NI,
1218 const DWARFDebugNames::NameTableEntry &NTE) {
Pavel Labathc9f07b02018-04-06 13:34:12 +00001219 // Verifying type unit indexes not supported.
1220 if (NI.getLocalTUCount() + NI.getForeignTUCount() > 0)
1221 return 0;
1222
Pavel Labathd6ca0632018-06-01 10:33:11 +00001223 const char *CStr = NTE.getString();
Pavel Labathc9f07b02018-04-06 13:34:12 +00001224 if (!CStr) {
1225 error() << formatv(
1226 "Name Index @ {0:x}: Unable to get string associated with name {1}.\n",
Pavel Labathd6ca0632018-06-01 10:33:11 +00001227 NI.getUnitOffset(), NTE.getIndex());
Pavel Labathc9f07b02018-04-06 13:34:12 +00001228 return 1;
1229 }
1230 StringRef Str(CStr);
1231
1232 unsigned NumErrors = 0;
1233 unsigned NumEntries = 0;
Pavel Labathd6ca0632018-06-01 10:33:11 +00001234 uint32_t EntryID = NTE.getEntryOffset();
1235 uint32_t NextEntryID = EntryID;
1236 Expected<DWARFDebugNames::Entry> EntryOr = NI.getEntry(&NextEntryID);
1237 for (; EntryOr; ++NumEntries, EntryID = NextEntryID,
1238 EntryOr = NI.getEntry(&NextEntryID)) {
Pavel Labathc9f07b02018-04-06 13:34:12 +00001239 uint32_t CUIndex = *EntryOr->getCUIndex();
1240 if (CUIndex > NI.getCUCount()) {
1241 error() << formatv("Name Index @ {0:x}: Entry @ {1:x} contains an "
1242 "invalid CU index ({2}).\n",
1243 NI.getUnitOffset(), EntryID, CUIndex);
1244 ++NumErrors;
1245 continue;
1246 }
1247 uint32_t CUOffset = NI.getCUOffset(CUIndex);
Pavel Labath4adc88e2018-06-13 08:14:27 +00001248 uint64_t DIEOffset = CUOffset + *EntryOr->getDIEUnitOffset();
Pavel Labathc9f07b02018-04-06 13:34:12 +00001249 DWARFDie DIE = DCtx.getDIEForOffset(DIEOffset);
1250 if (!DIE) {
1251 error() << formatv("Name Index @ {0:x}: Entry @ {1:x} references a "
1252 "non-existing DIE @ {2:x}.\n",
1253 NI.getUnitOffset(), EntryID, DIEOffset);
1254 ++NumErrors;
1255 continue;
1256 }
1257 if (DIE.getDwarfUnit()->getOffset() != CUOffset) {
1258 error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched CU of "
1259 "DIE @ {2:x}: index - {3:x}; debug_info - {4:x}.\n",
1260 NI.getUnitOffset(), EntryID, DIEOffset, CUOffset,
1261 DIE.getDwarfUnit()->getOffset());
1262 ++NumErrors;
1263 }
1264 if (DIE.getTag() != EntryOr->tag()) {
1265 error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Tag of "
1266 "DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1267 NI.getUnitOffset(), EntryID, DIEOffset, EntryOr->tag(),
1268 DIE.getTag());
1269 ++NumErrors;
1270 }
1271
1272 auto EntryNames = getNames(DIE);
1273 if (!is_contained(EntryNames, Str)) {
1274 error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Name "
1275 "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n",
1276 NI.getUnitOffset(), EntryID, DIEOffset, Str,
1277 make_range(EntryNames.begin(), EntryNames.end()));
Pavel Labath2a6afe52018-05-14 14:13:20 +00001278 ++NumErrors;
Pavel Labathc9f07b02018-04-06 13:34:12 +00001279 }
1280 }
1281 handleAllErrors(EntryOr.takeError(),
1282 [&](const DWARFDebugNames::SentinelError &) {
1283 if (NumEntries > 0)
1284 return;
1285 error() << formatv("Name Index @ {0:x}: Name {1} ({2}) is "
1286 "not associated with any entries.\n",
Pavel Labathd6ca0632018-06-01 10:33:11 +00001287 NI.getUnitOffset(), NTE.getIndex(), Str);
Pavel Labathc9f07b02018-04-06 13:34:12 +00001288 ++NumErrors;
1289 },
1290 [&](const ErrorInfoBase &Info) {
Pavel Labathd6ca0632018-06-01 10:33:11 +00001291 error()
1292 << formatv("Name Index @ {0:x}: Name {1} ({2}): {3}\n",
1293 NI.getUnitOffset(), NTE.getIndex(), Str,
1294 Info.message());
Pavel Labathc9f07b02018-04-06 13:34:12 +00001295 ++NumErrors;
1296 });
1297 return NumErrors;
1298}
1299
Pavel Labath80827f12018-05-15 13:24:10 +00001300static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) {
1301 Optional<DWARFFormValue> Location = Die.findRecursively(DW_AT_location);
1302 if (!Location)
1303 return false;
1304
1305 auto ContainsInterestingOperators = [&](StringRef D) {
1306 DWARFUnit *U = Die.getDwarfUnit();
1307 DataExtractor Data(D, DCtx.isLittleEndian(), U->getAddressByteSize());
1308 DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize());
1309 return any_of(Expression, [](DWARFExpression::Operation &Op) {
1310 return !Op.isError() && (Op.getCode() == DW_OP_addr ||
1311 Op.getCode() == DW_OP_form_tls_address ||
1312 Op.getCode() == DW_OP_GNU_push_tls_address);
1313 });
1314 };
1315
1316 if (Optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) {
1317 // Inlined location.
1318 if (ContainsInterestingOperators(toStringRef(*Expr)))
1319 return true;
1320 } else if (Optional<uint64_t> Offset = Location->getAsSectionOffset()) {
1321 // Location list.
1322 if (const DWARFDebugLoc *DebugLoc = DCtx.getDebugLoc()) {
1323 if (const DWARFDebugLoc::LocationList *LocList =
1324 DebugLoc->getLocationListAtOffset(*Offset)) {
1325 if (any_of(LocList->Entries, [&](const DWARFDebugLoc::Entry &E) {
1326 return ContainsInterestingOperators({E.Loc.data(), E.Loc.size()});
1327 }))
1328 return true;
1329 }
1330 }
1331 }
1332 return false;
1333}
1334
1335unsigned DWARFVerifier::verifyNameIndexCompleteness(
1336 const DWARFDie &Die, const DWARFDebugNames::NameIndex &NI) {
1337
1338 // First check, if the Die should be indexed. The code follows the DWARF v5
1339 // wording as closely as possible.
1340
1341 // "All non-defining declarations (that is, debugging information entries
1342 // with a DW_AT_declaration attribute) are excluded."
1343 if (Die.find(DW_AT_declaration))
1344 return 0;
1345
1346 // "DW_TAG_namespace debugging information entries without a DW_AT_name
1347 // attribute are included with the name “(anonymous namespace)”.
1348 // All other debugging information entries without a DW_AT_name attribute
1349 // are excluded."
1350 // "If a subprogram or inlined subroutine is included, and has a
1351 // DW_AT_linkage_name attribute, there will be an additional index entry for
1352 // the linkage name."
Jonas Devlieghere6e5c7e62018-09-03 12:12:17 +00001353 auto IncludeLinkageName = Die.getTag() == DW_TAG_subprogram ||
1354 Die.getTag() == DW_TAG_inlined_subroutine;
1355 auto EntryNames = getNames(Die, IncludeLinkageName);
Pavel Labath80827f12018-05-15 13:24:10 +00001356 if (EntryNames.empty())
1357 return 0;
1358
1359 // We deviate from the specification here, which says:
1360 // "The name index must contain an entry for each debugging information entry
1361 // that defines a named subprogram, label, variable, type, or namespace,
1362 // subject to ..."
1363 // Instead whitelisting all TAGs representing a "type" or a "subprogram", to
1364 // make sure we catch any missing items, we instead blacklist all TAGs that we
1365 // know shouldn't be indexed.
1366 switch (Die.getTag()) {
Jonas Devlieghere3a92c5c2018-08-03 12:01:43 +00001367 // Compile units and modules have names but shouldn't be indexed.
Pavel Labath80827f12018-05-15 13:24:10 +00001368 case DW_TAG_compile_unit:
Jonas Devlieghere3a92c5c2018-08-03 12:01:43 +00001369 case DW_TAG_module:
Pavel Labath80827f12018-05-15 13:24:10 +00001370 return 0;
1371
1372 // Function and template parameters are not globally visible, so we shouldn't
1373 // index them.
1374 case DW_TAG_formal_parameter:
1375 case DW_TAG_template_value_parameter:
1376 case DW_TAG_template_type_parameter:
1377 case DW_TAG_GNU_template_parameter_pack:
1378 case DW_TAG_GNU_template_template_param:
1379 return 0;
1380
1381 // Object members aren't globally visible.
1382 case DW_TAG_member:
1383 return 0;
1384
1385 // According to a strict reading of the specification, enumerators should not
1386 // be indexed (and LLVM currently does not do that). However, this causes
1387 // problems for the debuggers, so we may need to reconsider this.
1388 case DW_TAG_enumerator:
1389 return 0;
1390
1391 // Imported declarations should not be indexed according to the specification
1392 // and LLVM currently does not do that.
1393 case DW_TAG_imported_declaration:
1394 return 0;
1395
1396 // "DW_TAG_subprogram, DW_TAG_inlined_subroutine, and DW_TAG_label debugging
1397 // information entries without an address attribute (DW_AT_low_pc,
1398 // DW_AT_high_pc, DW_AT_ranges, or DW_AT_entry_pc) are excluded."
1399 case DW_TAG_subprogram:
1400 case DW_TAG_inlined_subroutine:
1401 case DW_TAG_label:
1402 if (Die.findRecursively(
1403 {DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_entry_pc}))
1404 break;
1405 return 0;
1406
1407 // "DW_TAG_variable debugging information entries with a DW_AT_location
1408 // attribute that includes a DW_OP_addr or DW_OP_form_tls_address operator are
1409 // included; otherwise, they are excluded."
1410 //
1411 // LLVM extension: We also add DW_OP_GNU_push_tls_address to this list.
1412 case DW_TAG_variable:
1413 if (isVariableIndexable(Die, DCtx))
1414 break;
1415 return 0;
1416
1417 default:
1418 break;
1419 }
1420
1421 // Now we know that our Die should be present in the Index. Let's check if
1422 // that's the case.
1423 unsigned NumErrors = 0;
Pavel Labath4adc88e2018-06-13 08:14:27 +00001424 uint64_t DieUnitOffset = Die.getOffset() - Die.getDwarfUnit()->getOffset();
Pavel Labath80827f12018-05-15 13:24:10 +00001425 for (StringRef Name : EntryNames) {
Pavel Labath4adc88e2018-06-13 08:14:27 +00001426 if (none_of(NI.equal_range(Name), [&](const DWARFDebugNames::Entry &E) {
1427 return E.getDIEUnitOffset() == DieUnitOffset;
Pavel Labath80827f12018-05-15 13:24:10 +00001428 })) {
1429 error() << formatv("Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
1430 "name {3} missing.\n",
1431 NI.getUnitOffset(), Die.getOffset(), Die.getTag(),
1432 Name);
1433 ++NumErrors;
1434 }
1435 }
1436 return NumErrors;
1437}
1438
Pavel Labathb136c392018-03-08 15:34:42 +00001439unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection,
1440 const DataExtractor &StrData) {
1441 unsigned NumErrors = 0;
1442 DWARFDataExtractor AccelSectionData(DCtx.getDWARFObj(), AccelSection,
1443 DCtx.isLittleEndian(), 0);
1444 DWARFDebugNames AccelTable(AccelSectionData, StrData);
1445
1446 OS << "Verifying .debug_names...\n";
1447
1448 // This verifies that we can read individual name indices and their
1449 // abbreviation tables.
1450 if (Error E = AccelTable.extract()) {
1451 error() << toString(std::move(E)) << '\n';
1452 return 1;
1453 }
1454
1455 NumErrors += verifyDebugNamesCULists(AccelTable);
Pavel Labath906b7772018-03-16 10:02:16 +00001456 for (const auto &NI : AccelTable)
1457 NumErrors += verifyNameIndexBuckets(NI, StrData);
Pavel Labath79cd9422018-03-22 14:50:44 +00001458 for (const auto &NI : AccelTable)
1459 NumErrors += verifyNameIndexAbbrevs(NI);
Pavel Labathb136c392018-03-08 15:34:42 +00001460
Pavel Labathc9f07b02018-04-06 13:34:12 +00001461 // Don't attempt Entry validation if any of the previous checks found errors
1462 if (NumErrors > 0)
1463 return NumErrors;
1464 for (const auto &NI : AccelTable)
Pavel Labathd6ca0632018-06-01 10:33:11 +00001465 for (DWARFDebugNames::NameTableEntry NTE : NI)
1466 NumErrors += verifyNameIndexEntries(NI, NTE);
Pavel Labathc9f07b02018-04-06 13:34:12 +00001467
Pavel Labath80827f12018-05-15 13:24:10 +00001468 if (NumErrors > 0)
1469 return NumErrors;
1470
Paul Robinson143eaea2018-08-01 20:43:47 +00001471 for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units()) {
Pavel Labath80827f12018-05-15 13:24:10 +00001472 if (const DWARFDebugNames::NameIndex *NI =
Paul Robinson143eaea2018-08-01 20:43:47 +00001473 AccelTable.getCUNameIndex(U->getOffset())) {
1474 auto *CU = cast<DWARFCompileUnit>(U.get());
Pavel Labath80827f12018-05-15 13:24:10 +00001475 for (const DWARFDebugInfoEntry &Die : CU->dies())
Paul Robinson143eaea2018-08-01 20:43:47 +00001476 NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI);
Pavel Labath80827f12018-05-15 13:24:10 +00001477 }
1478 }
Pavel Labathb136c392018-03-08 15:34:42 +00001479 return NumErrors;
1480}
1481
Spyridoula Gravanidc635f42017-07-26 00:52:31 +00001482bool DWARFVerifier::handleAccelTables() {
1483 const DWARFObject &D = DCtx.getDWARFObj();
1484 DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0);
1485 unsigned NumErrors = 0;
1486 if (!D.getAppleNamesSection().Data.empty())
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +00001487 NumErrors += verifyAppleAccelTable(&D.getAppleNamesSection(), &StrData,
1488 ".apple_names");
Spyridoula Gravanidc635f42017-07-26 00:52:31 +00001489 if (!D.getAppleTypesSection().Data.empty())
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +00001490 NumErrors += verifyAppleAccelTable(&D.getAppleTypesSection(), &StrData,
1491 ".apple_types");
Spyridoula Gravanidc635f42017-07-26 00:52:31 +00001492 if (!D.getAppleNamespacesSection().Data.empty())
Pavel Labath9b36fd22018-01-22 13:17:23 +00001493 NumErrors += verifyAppleAccelTable(&D.getAppleNamespacesSection(), &StrData,
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +00001494 ".apple_namespaces");
Spyridoula Gravanidc635f42017-07-26 00:52:31 +00001495 if (!D.getAppleObjCSection().Data.empty())
Jonas Devlieghere9d7cecf2018-09-17 14:23:47 +00001496 NumErrors += verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData,
1497 ".apple_objc");
Pavel Labathb136c392018-03-08 15:34:42 +00001498
1499 if (!D.getDebugNamesSection().Data.empty())
1500 NumErrors += verifyDebugNames(D.getDebugNamesSection(), StrData);
Spyridoula Gravanidc635f42017-07-26 00:52:31 +00001501 return NumErrors == 0;
Spyridoula Gravanie41823b2017-06-14 00:17:55 +00001502}
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +00001503
Jonas Devlieghere6be1f012018-04-15 08:44:15 +00001504raw_ostream &DWARFVerifier::error() const { return WithColor::error(OS); }
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +00001505
Jonas Devlieghere6be1f012018-04-15 08:44:15 +00001506raw_ostream &DWARFVerifier::warn() const { return WithColor::warning(OS); }
Jonas Devlieghere19fc4d92017-09-29 09:33:31 +00001507
Jonas Devlieghere6be1f012018-04-15 08:44:15 +00001508raw_ostream &DWARFVerifier::note() const { return WithColor::note(OS); }
Jonas Devliegheref1f3e732018-09-19 08:08:13 +00001509
1510raw_ostream &DWARFVerifier::dump(const DWARFDie &Die, unsigned indent) const {
1511 Die.dump(OS, indent, DumpOpts);
1512 return OS;
1513}