std.debug.Coverage.resolveAddressesDwarf: fix broken logic

The implementation assumed that compilation units did not overlap, which
is not the case. The new implementation uses .debug_ranges to iterate
over the requested PCs.

This partially resolves #20990. The dump-cov tool is fixed but the same
fix needs to be applied to `std.Build.Fuzz.WebServer` (sorting the PC
list before passing it to be resolved by debug info).

I am observing LLVM emit multiple 8-bit counters for the same PC
addresses when enabling `-fsanitize-coverage=inline-8bit-counters`. This
seems like a bug in LLVM. I can't fathom why that would be desireable.
This commit is contained in:
Andrew Kelley
2024-08-09 19:49:48 -07:00
parent 0b5ea2b902
commit b5398180d6
5 changed files with 91 additions and 76 deletions

View File

@@ -54,21 +54,30 @@ pub fn main() !void {
const header: *SeenPcsHeader = @ptrCast(cov_bytes);
try stdout.print("{any}\n", .{header.*});
const pcs = header.pcAddrs();
for (0.., pcs[0 .. pcs.len - 1], pcs[1..]) |i, a, b| {
if (a > b) std.log.err("{d}: 0x{x} > 0x{x}", .{ i, a, b });
}
assert(std.sort.isSorted(usize, pcs, {}, std.sort.asc(usize)));
var indexed_pcs: std.AutoArrayHashMapUnmanaged(usize, void) = .{};
try indexed_pcs.entries.resize(arena, pcs.len);
@memcpy(indexed_pcs.entries.items(.key), pcs);
try indexed_pcs.reIndex(arena);
const sorted_pcs = try arena.dupe(usize, pcs);
std.mem.sortUnstable(usize, sorted_pcs, {}, std.sort.asc(usize));
const source_locations = try arena.alloc(std.debug.Coverage.SourceLocation, sorted_pcs.len);
try debug_info.resolveAddresses(gpa, sorted_pcs, source_locations);
const seen_pcs = header.seenBits();
const source_locations = try arena.alloc(std.debug.Coverage.SourceLocation, pcs.len);
try debug_info.resolveAddresses(gpa, pcs, source_locations);
for (pcs, source_locations, 0..) |pc, sl, i| {
for (sorted_pcs, source_locations) |pc, sl| {
if (sl.file == .invalid) {
try stdout.print(" {x}: invalid\n", .{pc});
continue;
}
const file = debug_info.coverage.fileAt(sl.file);
const dir_name = debug_info.coverage.directories.keys()[file.directory_index];
const dir_name_slice = debug_info.coverage.stringAt(dir_name);
const hit: u1 = @truncate(seen_pcs[i / @bitSizeOf(usize)] >> @intCast(i % @bitSizeOf(usize)));
const seen_i = indexed_pcs.getIndex(pc).?;
const hit: u1 = @truncate(seen_pcs[seen_i / @bitSizeOf(usize)] >> @intCast(seen_i % @bitSizeOf(usize)));
try stdout.print("{c}{x}: {s}/{s}:{d}:{d}\n", .{
"-+"[hit], pc, dir_name_slice, debug_info.coverage.stringAt(file.basename), sl.line, sl.column,
});