Skip to content

Modify dwarf verification JSON to include detailed counts by sub-category #128018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,28 @@ class DWARFDebugAbbrev;
class DataExtractor;
struct DWARFSection;

struct AggregationData {
unsigned OverallCount;
std::map<std::string, unsigned> DetailedCounts;
};

class OutputCategoryAggregator {
private:
std::map<std::string, unsigned> Aggregation;
std::map<std::string, AggregationData> Aggregation;
bool IncludeDetail;

public:
OutputCategoryAggregator(bool includeDetail = false)
: IncludeDetail(includeDetail) {}
void ShowDetail(bool showDetail) { IncludeDetail = showDetail; }
size_t GetNumCategories() const { return Aggregation.size(); }
void Report(StringRef s, std::function<void()> detailCallback);
void Report(StringRef category, std::function<void()> detailCallback);
void Report(StringRef category, StringRef sub_category,
std::function<void()> detailCallback);
void EnumerateResults(std::function<void(StringRef, unsigned)> handleCounts);
void EnumerateDetailedResultsFor(
StringRef category,
std::function<void(StringRef, unsigned)> handleCounts);
};

/// A class that verifies DWARF debug information given a DWARF Context.
Expand Down
46 changes: 37 additions & 9 deletions llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,12 +1941,14 @@ unsigned DWARFVerifier::verifyNameIndexCompleteness(
if (none_of(NI.equal_range(Name), [&](const DWARFDebugNames::Entry &E) {
return E.getDIEUnitOffset() == DieUnitOffset;
})) {
ErrorCategory.Report("Name Index DIE entry missing name", [&]() {
error() << formatv(
"Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
"name {3} missing.\n",
NI.getUnitOffset(), Die.getOffset(), Die.getTag(), Name);
});
ErrorCategory.Report(
"Name Index DIE entry missing name",
llvm::dwarf::TagString(Die.getTag()), [&]() {
error() << formatv(
"Name Index @ {0:x}: Entry for DIE @ {1:x} ({2}) with "
"name {3} missing.\n",
NI.getUnitOffset(), Die.getOffset(), Die.getTag(), Name);
});
++NumErrors;
}
}
Expand Down Expand Up @@ -2168,15 +2170,35 @@ bool DWARFVerifier::verifyDebugStrOffsets(

void OutputCategoryAggregator::Report(
StringRef s, std::function<void(void)> detailCallback) {
Aggregation[std::string(s)]++;
this->Report(s, "", detailCallback);
}

void OutputCategoryAggregator::Report(
StringRef category, StringRef sub_category,
std::function<void(void)> detailCallback) {
std::string category_str = std::string(category);
AggregationData &Agg = Aggregation[category_str];
Agg.OverallCount++;
if (!sub_category.empty()) {
Agg.DetailedCounts[std::string(sub_category)]++;
}
if (IncludeDetail)
detailCallback();
}

void OutputCategoryAggregator::EnumerateResults(
std::function<void(StringRef, unsigned)> handleCounts) {
for (auto &&[name, count] : Aggregation) {
handleCounts(name, count);
for (const auto &[name, aggData] : Aggregation) {
handleCounts(name, aggData.OverallCount);
}
}
void OutputCategoryAggregator::EnumerateDetailedResultsFor(
StringRef category, std::function<void(StringRef, unsigned)> handleCounts) {
const auto Agg = Aggregation.find(std::string(category));
if (Agg != Aggregation.end()) {
for (const auto &[name, aggData] : Agg->second.DetailedCounts) {
handleCounts(name, aggData);
}
}
}

Expand All @@ -2203,6 +2225,12 @@ void DWARFVerifier::summarize() {
ErrorCategory.EnumerateResults([&](StringRef Category, unsigned Count) {
llvm::json::Object Val;
Val.try_emplace("count", Count);
llvm::json::Object Details;
ErrorCategory.EnumerateDetailedResultsFor(
Category, [&](StringRef SubCategory, unsigned SubCount) {
Details.try_emplace(SubCategory, SubCount);
});
Val.try_emplace("details", std::move(Details));
Categories.try_emplace(Category, std::move(Val));
ErrorCount += Count;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj -o - | not llvm-dwarfdump -verify --verify-json=%t.json -
# RUN: FileCheck %s --input-file %t.json

# CHECK: {"error-categories":{"Name Index DIE entry missing name":{"count":10}},"error-count":10}
# CHECK: {"error-categories":{"Name Index DIE entry missing name":{"count":10,"details":{"DW_TAG_inlined_subroutine":1,"DW_TAG_label":1,"DW_TAG_namespace":2,"DW_TAG_subprogram":2,"DW_TAG_variable":4}}},"error-count":10}
# CHECK-NOT: error: Name Index @ 0x0: Entry for DIE @ {{.*}} (DW_TAG_variable) with name var_block_addr missing.

.section .debug_loc,"",@progbits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# RUN: not llvm-dwarfdump -verify -verify-json=%t.json -
# RUN: FileCheck %s --input-file %t.json

# CHECK: {"error-categories":{"Duplicate Name Index":{"count":1},"Name Index doesn't index any CU":{"count":1},"Name Index references non-existing CU":{"count":1}},"error-count":3}
# CHECK: {"error-categories":{"Duplicate Name Index":{"count":1,"details":{}},"Name Index doesn't index any CU":{"count":1,"details":{}},"Name Index references non-existing CU":{"count":1,"details":{}}},"error-count":3}
# CHECK-NOT : error: Name Index @ 0x58 references a CU @ 0x0, but this CU is already indexed by Name Index @ 0x28
# CHECK-NOT: warning: CU @ 0x13 not covered by any Name Index

Expand Down