[llvm] [DebugInfo] Avoid std::function in DWARF verifier internals (PR #202866)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 06:21:21 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-debuginfo
Author: David Zbarsky (dzbarsky)
<details>
<summary>Changes</summary>
Avoid constructing `std::function` at DWARF verifier diagnostic sites by routing internal synchronous callbacks through private `function_ref` helpers. The public `LLVM_ABI` methods and class layout remain unchanged.
On arm64 Release builds, this reduces stripped `llvm-dwarfdump` by 33,536 bytes, `DWARFVerifier.cpp.o` by 175,736 bytes, and object relocations by 2,333. Diagnostics were byte-identical across 66 generated verifier inputs; valid and malformed verification benchmarks were neutral within their 95% confidence intervals.
Work towards #<!-- -->202616
AI tool disclosure: Co-authored with OpenAI Codex.
---
Patch is 39.28 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/202866.diff
2 Files Affected:
- (modified) llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h (+11)
- (modified) llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp (+100-80)
``````````diff
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index f667496ab1059..08a149579b2a5 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -9,6 +9,7 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
+#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
@@ -31,6 +32,7 @@ struct DWARFAttribute;
class DWARFContext;
class DWARFDataExtractor;
class DWARFDebugAbbrev;
+class DWARFVerifier;
class DataExtractor;
struct DWARFSection;
@@ -41,11 +43,20 @@ struct AggregationData {
class OutputCategoryAggregator {
private:
+ friend class DWARFVerifier;
+
std::mutex WriteMutex;
std::map<std::string, AggregationData, std::less<>> Aggregation;
uint64_t NumErrors = 0;
bool IncludeDetail;
+ void report(StringRef category, function_ref<void()> detailCallback);
+ void report(StringRef category, StringRef sub_category,
+ function_ref<void()> detailCallback);
+ void enumerateResults(function_ref<void(StringRef, unsigned)> handleCounts);
+ void enumerateDetailedResultsFor(
+ StringRef category, function_ref<void(StringRef, unsigned)> handleCounts);
+
public:
OutputCategoryAggregator(bool includeDetail = false)
: IncludeDetail(includeDetail) {}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 17d1bfb3f575c..d9a15fb5a998f 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -207,26 +207,26 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
}
};
if (!ValidLength)
- ErrorCategory.Report(
+ ErrorCategory.report(
"Unit Header Length: Unit too large for .debug_info provided", [&]() {
ShowHeaderOnce();
note() << "The length for this unit is too "
"large for the .debug_info provided.\n";
});
if (!ValidVersion)
- ErrorCategory.Report(
+ ErrorCategory.report(
"Unit Header Length: 16 bit unit header version is not valid", [&]() {
ShowHeaderOnce();
note() << "The 16 bit unit header version is not valid.\n";
});
if (!ValidType)
- ErrorCategory.Report(
+ ErrorCategory.report(
"Unit Header Length: Unit type encoding is not valid", [&]() {
ShowHeaderOnce();
note() << "The unit type encoding is not valid.\n";
});
if (!ValidAbbrevOffset)
- ErrorCategory.Report(
+ ErrorCategory.report(
"Unit Header Length: Offset into the .debug_abbrev section is not "
"valid",
[&]() {
@@ -235,7 +235,7 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
"not valid.\n";
});
if (!ValidAddrSize)
- ErrorCategory.Report("Unit Header Length: Address size is unsupported",
+ ErrorCategory.report("Unit Header Length: Address size is unsupported",
[&]() {
ShowHeaderOnce();
note() << "The address size is unsupported.\n";
@@ -256,7 +256,7 @@ bool DWARFVerifier::verifyName(const DWARFDie &Die) {
if (OriginalFullName.empty() || OriginalFullName == ReconstructedName)
return false;
- ErrorCategory.Report(
+ ErrorCategory.report(
"Simplified template DW_AT_name could not be reconstituted", [&]() {
error()
<< "Simplified template DW_AT_name could not be reconstituted:\n"
@@ -302,7 +302,7 @@ unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit,
DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false);
if (!Die) {
- ErrorCategory.Report("Compilation unit missing DIE", [&]() {
+ ErrorCategory.report("Compilation unit missing DIE", [&]() {
error() << "Compilation unit without DIE.\n";
});
NumUnitErrors++;
@@ -310,7 +310,7 @@ unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit,
}
if (!dwarf::isUnitType(Die.getTag())) {
- ErrorCategory.Report("Compilation unit root DIE is not a unit DIE", [&]() {
+ ErrorCategory.report("Compilation unit root DIE is not a unit DIE", [&]() {
error() << formatv("Compilation unit root DIE is not a unit DIE: {0}.\n",
dwarf::TagString(Die.getTag()));
});
@@ -319,7 +319,7 @@ unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit,
uint8_t UnitType = Unit.getUnitType();
if (!DWARFUnit::isMatchingUnitTypeAndTag(UnitType, Die.getTag())) {
- ErrorCategory.Report("Mismatched unit type", [&]() {
+ ErrorCategory.report("Mismatched unit type", [&]() {
error() << formatv(
"Compilation unit type ({0}) and root DIE ({1}) do not match.\n",
dwarf::UnitTypeString(UnitType), dwarf::TagString(Die.getTag()));
@@ -331,7 +331,7 @@ unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit,
// 3.1.2 Skeleton Compilation Unit Entries:
// "A skeleton compilation unit has no children."
if (Die.getTag() == dwarf::DW_TAG_skeleton_unit && Die.hasChildren()) {
- ErrorCategory.Report("Skeleton CU has children", [&]() {
+ ErrorCategory.report("Skeleton CU has children", [&]() {
error() << "Skeleton compilation unit has children.\n";
});
NumUnitErrors++;
@@ -350,7 +350,7 @@ unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
DWARFDie Curr = Die.getParent();
for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Curr.getParent()) {
if (Curr.getTag() == DW_TAG_inlined_subroutine) {
- ErrorCategory.Report(
+ ErrorCategory.report(
"Call site nested entry within inlined subroutine", [&]() {
error() << "Call site entry nested within inlined subroutine:";
Curr.dump(OS);
@@ -360,7 +360,7 @@ unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
}
if (!Curr.isValid()) {
- ErrorCategory.Report(
+ ErrorCategory.report(
"Call site entry not nested within valid subprogram", [&]() {
error() << "Call site entry not nested within a valid subprogram:";
Die.dump(OS);
@@ -373,7 +373,7 @@ unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) {
DW_AT_call_all_tail_calls, DW_AT_GNU_all_call_sites,
DW_AT_GNU_all_source_call_sites, DW_AT_GNU_all_tail_call_sites});
if (!CallAttr) {
- ErrorCategory.Report(
+ ErrorCategory.report(
"Subprogram with call site entry has no DW_AT_call attribute", [&]() {
error()
<< "Subprogram with call site entry has no DW_AT_call attribute:";
@@ -394,7 +394,7 @@ unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
Abbrev->getAbbreviationDeclarationSet(0);
if (!AbbrDeclsOrErr) {
std::string ErrMsg = toString(AbbrDeclsOrErr.takeError());
- ErrorCategory.Report("Abbreviation Declaration error",
+ ErrorCategory.report("Abbreviation Declaration error",
[&]() { error() << ErrMsg << "\n"; });
return 1;
}
@@ -406,7 +406,7 @@ unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) {
for (auto Attribute : AbbrDecl.attributes()) {
auto Result = AttributeSet.insert(Attribute.Attr);
if (!Result.second) {
- ErrorCategory.Report(
+ ErrorCategory.report(
"Abbreviation declartion contains multiple attributes", [&]() {
error() << formatv("Abbreviation declaration contains multiple "
"{0} attributes.\n",
@@ -526,7 +526,7 @@ unsigned DWARFVerifier::verifyIndex(StringRef Name,
StringRef Category = InfoColumnKind == DWARFSectionKind::DW_SECT_INFO
? "Overlapping CU index entries"
: "Overlapping TU index entries";
- ErrorCategory.Report(Category, [&]() {
+ ErrorCategory.report(Category, [&]() {
error() << llvm::formatv(
"overlapping index entries for entries {0:x16} "
"and {1:x16} for column {2}\n",
@@ -618,7 +618,7 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
for (const auto &Range : Ranges) {
if (!Range.valid()) {
++NumErrors;
- ErrorCategory.Report("Invalid address range", [&]() {
+ ErrorCategory.report("Invalid address range", [&]() {
error() << formatv("Invalid address range {0}\n", Range);
DumpDieAfterError = true;
});
@@ -633,7 +633,7 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
// address: 0 or -1.
if (auto PrevRange = RI.insert(Range)) {
++NumErrors;
- ErrorCategory.Report("DIE has overlapping DW_AT_ranges", [&]() {
+ ErrorCategory.report("DIE has overlapping DW_AT_ranges", [&]() {
error() << formatv("DIE has overlapping ranges in DW_AT_ranges "
"attribute: {0} and {1}\n",
*PrevRange, Range);
@@ -649,7 +649,7 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
const auto IntersectingChild = ParentRI.insert(RI);
if (IntersectingChild != ParentRI.Children.end()) {
++NumErrors;
- ErrorCategory.Report("DIEs have overlapping address ranges", [&]() {
+ ErrorCategory.report("DIEs have overlapping address ranges", [&]() {
error() << "DIEs have overlapping address ranges:";
dump(Die);
dump(IntersectingChild->Die) << '\n';
@@ -662,7 +662,7 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die,
ParentRI.Die.getTag() == DW_TAG_subprogram);
if (ShouldBeContained && !ParentRI.contains(RI)) {
++NumErrors;
- ErrorCategory.Report(
+ ErrorCategory.report(
"DIE address ranges are not contained by parent ranges", [&]() {
error()
<< "DIE address ranges are not contained in its parent's ranges:";
@@ -712,7 +712,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
unsigned NumErrors = 0;
auto ReportError = [&](StringRef category, const Twine &TitleMsg) {
++NumErrors;
- ErrorCategory.Report(category, [&]() {
+ ErrorCategory.report(category, [&]() {
error() << formatv("{0}\n", TitleMsg);
dump(Die) << '\n';
});
@@ -974,7 +974,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
auto CUOffset = AttrValue.Value.getRawUValue();
if (CUOffset >= CUSize) {
++NumErrors;
- ErrorCategory.Report("Invalid CU offset", [&]() {
+ ErrorCategory.report("Invalid CU offset", [&]() {
error() << formatv("{0} CU offset {1:x+8} is invalid (must be less "
"than CU size of {2:x+8}):\n",
FormEncodingString(Form), CUOffset, CUSize);
@@ -998,7 +998,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
if (RefVal) {
if (*RefVal >= DieCU->getInfoSection().Data.size()) {
++NumErrors;
- ErrorCategory.Report("DW_FORM_ref_addr offset out of bounds", [&]() {
+ ErrorCategory.report("DW_FORM_ref_addr offset out of bounds", [&]() {
error() << "DW_FORM_ref_addr offset beyond .debug_info "
"bounds:\n";
dump(Die) << '\n';
@@ -1021,7 +1021,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
if (Error E = AttrValue.Value.getAsCString().takeError()) {
++NumErrors;
std::string ErrMsg = toString(std::move(E));
- ErrorCategory.Report("Invalid DW_FORM attribute", [&]() {
+ ErrorCategory.report("Invalid DW_FORM attribute", [&]() {
error() << formatv("{0}:\n", ErrMsg);
dump(Die) << '\n';
});
@@ -1047,7 +1047,7 @@ unsigned DWARFVerifier::verifyDebugInfoReferences(
if (GetDIEForOffset(Pair.first))
continue;
++NumErrors;
- ErrorCategory.Report("Invalid DIE reference", [&]() {
+ ErrorCategory.report("Invalid DIE reference", [&]() {
error() << formatv(
"invalid DIE reference {0:x+8}. Offset is in between DIEs:\n",
Pair.first);
@@ -1074,7 +1074,7 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() {
if (LineTableOffset < DCtx.getDWARFObj().getLineSection().Data.size()) {
if (!LineTable) {
++NumDebugLineErrors;
- ErrorCategory.Report("Unparsable .debug_line entry", [&]() {
+ ErrorCategory.report("Unparsable .debug_line entry", [&]() {
error() << formatv(
".debug_line[{0:x+8}] was not able to be parsed for CU:\n",
LineTableOffset);
@@ -1093,7 +1093,7 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() {
if (!Inserted) {
++NumDebugLineErrors;
const auto &OldDie = Iter->second;
- ErrorCategory.Report("Identical DW_AT_stmt_list section offset", [&]() {
+ ErrorCategory.report("Identical DW_AT_stmt_list section offset", [&]() {
error() << formatv("two compile unit DIEs, {0:x+8} and {1:x+8}, have "
"the same DW_AT_stmt_list section offset:\n",
OldDie.getOffset(), Die.getOffset());
@@ -1124,7 +1124,7 @@ void DWARFVerifier::verifyDebugLineRows() {
// Verify directory index.
if (FileName.DirIdx > MaxDirIndex) {
++NumDebugLineErrors;
- ErrorCategory.Report(
+ ErrorCategory.report(
"Invalid index in .debug_line->prologue.file_names->dir_idx",
[&]() {
error() << formatv(".debug_line[{0:x+8}].prologue.file_names[{1}]"
@@ -1164,7 +1164,7 @@ void DWARFVerifier::verifyDebugLineRows() {
// Verify row address.
if (Row.Address.Address < PrevAddress) {
++NumDebugLineErrors;
- ErrorCategory.Report(
+ ErrorCategory.report(
"decreasing address between debug_line rows", [&]() {
error() << formatv(".debug_line[{0:x+8}] row[{1}] decreases in "
"address from previous row:\n",
@@ -1181,7 +1181,7 @@ void DWARFVerifier::verifyDebugLineRows() {
if (!LineTable->hasFileAtIndex(Row.File)) {
++NumDebugLineErrors;
- ErrorCategory.Report("Invalid file index in debug_line", [&]() {
+ ErrorCategory.report("Invalid file index in debug_line", [&]() {
error() << formatv(".debug_line[{0:x+8}][{1}] has invalid file index "
"{2} (valid values are [{3},{4}{5}):\n",
*toSectionOffset(Die.find(DW_AT_stmt_list)),
@@ -1233,7 +1233,7 @@ void DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
// Verify that the fixed part of the header is not too short.
if (!AccelSectionData.isValidOffset(AccelTable.getSizeHdr())) {
- ErrorCategory.Report("Section is too small to fit a section header", [&]() {
+ ErrorCategory.report("Section is too small to fit a section header", [&]() {
error() << "Section is too small to fit a section header.\n";
});
return;
@@ -1242,7 +1242,7 @@ void DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
// Verify that the section is not too short.
if (Error E = AccelTable.extract()) {
std::string Msg = toString(std::move(E));
- ErrorCategory.Report("Section is too small to fit a section header",
+ ErrorCategory.report("Section is too small to fit a section header",
[&]() { error() << Msg << '\n'; });
return;
}
@@ -1258,7 +1258,7 @@ void DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
uint32_t HashIdx = AccelSectionData.getU32(&BucketsOffset);
if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
- ErrorCategory.Report("Invalid hash index", [&]() {
+ ErrorCategory.report("Invalid hash index", [&]() {
error() << formatv("Bucket[{0}] has invalid hash index: {1}.\n",
BucketIdx, HashIdx);
});
@@ -1266,13 +1266,13 @@ void DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
}
uint32_t NumAtoms = AccelTable.getAtomsDesc().size();
if (NumAtoms == 0) {
- ErrorCategory.Report("No atoms", [&]() {
+ ErrorCategory.report("No atoms", [&]() {
error() << "No atoms: failed to read HashData.\n";
});
return;
}
if (!AccelTable.validateForms()) {
- ErrorCategory.Report("Unsupported form", [&]() {
+ ErrorCategory.report("Unsupported form", [&]() {
error() << "Unsupported form: failed to read HashData.\n";
});
return;
@@ -1285,7 +1285,7 @@ void DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
uint64_t HashDataOffset = AccelSectionData.getU32(&DataOffset);
if (!AccelSectionData.isValidOffsetForDataOfSize(HashDataOffset,
sizeof(uint64_t))) {
- ErrorCategory.Report("Invalid HashData offset", [&]() {
+ ErrorCategory.report("Invalid HashData offset", [&]() {
error() << formatv("Hash[{0}] has invalid HashData offset: {1:x+8}.\n",
HashIdx, HashDataOffset);
});
@@ -1311,7 +1311,7 @@ void DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
if (!Name)
Name = "<NULL>";
- ErrorCategory.Report("Invalid DIE offset", [&]() {
+ ErrorCategory.report("Invalid DIE offset", [&]() {
error() << formatv("{0} Bucket[{1}] Hash[{2}] = {3:x+8} "
"Str[{4}] = {5:x+8} DIE[{6}] = {7:x+8} "
"is not a valid DIE offset for \"{8}\".\n",
@@ -1322,7 +1322,7 @@ void DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection,
continue;
}
if ((Tag != dwarf::DW_TAG_null) && (Die.getTag() != Tag)) {
- ErrorCategory.Report("Mismatched Tag in accellerator table", [&]() {
+ ErrorCategory.report("Mismatched Tag in accellerator table", [&]() {
error() << formatv("Tag {0} in accelerator table does not match "
"Tag {1} of DIE[{2}].\n",
dwarf::TagString(Tag),
@@ -1346,7 +1346,7 @@ void DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) {
parallelForEach(AccelTable, [&](const DWARFDebugNames::NameIndex &NI) {
if (NI.getCUCount() == 0) {
- ErrorCategory.Report("Name Index doesn't index any CU", [&]() {
+ ErrorCategory.report("Name Index doesn't index any CU", [&]() {
error() << formatv("Name Index @ {0:x} does not index any CU\n",
NI.getUnitOffset());
});
@@ -1355,7 +1355,7 @@ void DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) {
for (uint32_t CU = 0, End = NI.getCUCount(); CU < End; ++CU) {
uint64_t Offset = NI.getCUOffset(CU);
if (!CUOffsets.count(Offset)) {
- ErrorCategory.Report("Name Index references non-existing CU", [&]() {
+ ErrorCategory.report("Name Index references non-existing CU", [&]() {
error() << formatv(
"Name Index @ {0:x} references a non-existing CU @ {1:x}\n",
NI.getUnitOffset(), Offset);
@@ -1372,7 +1372,7 @@ void DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) {
CUMap[Offset] = NI.getUnitOffset();
}
if (DuplicateCUOffset) {
- ErrorCategory.Report("Duplicate Name Index", [&]() {
+ ErrorCategory.report("Duplicate Name Index", [&]() {
error() << formatv(
"Name Index @ {0:x} references a CU @ {1:x}, but "
"this CU is already indexed by Name Index @ {2:x}\n",
@@ -1415,7 +1415,7 @@ void DWARFVerifier::verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
for (uint32_t Bucket = 0, End = NI.getBucketCount(); Bucket < End; ++Bucket) {
uint32_t Index = NI.getBucketArrayEntry(Bucket);
if (Index > NI.getNameCount()) {
- ErrorCategory.Repor...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/202866
More information about the llvm-commits
mailing list