Skip to content

Commit

Permalink
Merge pull request #21075 from ziglang/fuzz
Browse files Browse the repository at this point in the history
fix several debug info bugs
  • Loading branch information
andrewrk authored Aug 14, 2024
2 parents b470d2a + 72768bd commit b7a1ef3
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 101 deletions.
24 changes: 21 additions & 3 deletions lib/std/Build/Fuzz/WebServer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -634,10 +634,28 @@ fn prepareTables(
const pcs = header.pcAddrs();
const source_locations = try gpa.alloc(Coverage.SourceLocation, pcs.len);
errdefer gpa.free(source_locations);
debug_info.resolveAddresses(gpa, pcs, source_locations) catch |err| {

// Unfortunately the PCs array that LLVM gives us from the 8-bit PC
// counters feature is not sorted.
var sorted_pcs: std.MultiArrayList(struct { pc: u64, index: u32, sl: Coverage.SourceLocation }) = .{};
defer sorted_pcs.deinit(gpa);
try sorted_pcs.resize(gpa, pcs.len);
@memcpy(sorted_pcs.items(.pc), pcs);
for (sorted_pcs.items(.index), 0..) |*v, i| v.* = @intCast(i);
sorted_pcs.sortUnstable(struct {
addrs: []const u64,

pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
return ctx.addrs[a_index] < ctx.addrs[b_index];
}
}{ .addrs = sorted_pcs.items(.pc) });

debug_info.resolveAddresses(gpa, sorted_pcs.items(.pc), sorted_pcs.items(.sl)) catch |err| {
log.err("failed to resolve addresses to source locations: {s}", .{@errorName(err)});
return error.AlreadyReported;
};

for (sorted_pcs.items(.index), sorted_pcs.items(.sl)) |i, sl| source_locations[i] = sl;
gop.value_ptr.source_locations = source_locations;

ws.coverage_condition.broadcast();
Expand All @@ -664,8 +682,8 @@ fn addEntryPoint(ws: *WebServer, coverage_id: u64, addr: u64) error{ AlreadyRepo
if (false) {
const sl = coverage_map.source_locations[index];
const file_name = coverage_map.coverage.stringAt(coverage_map.coverage.fileAt(sl.file).basename);
log.debug("server found entry point {s}:{d}:{d}", .{
file_name, sl.line, sl.column,
log.debug("server found entry point for 0x{x} at {s}:{d}:{d}", .{
addr, file_name, sl.line, sl.column,
});
}
const gpa = ws.gpa;
Expand Down
66 changes: 35 additions & 31 deletions lib/std/debug/Coverage.zig
Original file line number Diff line number Diff line change
Expand Up @@ -145,60 +145,64 @@ pub const ResolveAddressesDwarfError = Dwarf.ScanError;
pub fn resolveAddressesDwarf(
cov: *Coverage,
gpa: Allocator,
/// Asserts the addresses are in ascending order.
sorted_pc_addrs: []const u64,
/// Asserts its length equals length of `sorted_pc_addrs`.
output: []SourceLocation,
d: *Dwarf,
) ResolveAddressesDwarfError!void {
assert(sorted_pc_addrs.len == output.len);
assert(d.compile_units_sorted);
assert(d.ranges.items.len != 0); // call `populateRanges` first.

var cu_i: usize = 0;
var line_table_i: usize = 0;
var cu: *Dwarf.CompileUnit = &d.compile_unit_list.items[0];
var range = cu.pc_range.?;
var range_i: usize = 0;
var range: *std.debug.Dwarf.Range = &d.ranges.items[0];
var line_table_i: usize = undefined;
var prev_pc: u64 = 0;
var prev_cu: ?*std.debug.Dwarf.CompileUnit = null;
// Protects directories and files tables from other threads.
cov.mutex.lock();
defer cov.mutex.unlock();
next_pc: for (sorted_pc_addrs, output) |pc, *out| {
assert(pc >= prev_pc);
prev_pc = pc;

while (pc >= range.end) {
cu_i += 1;
if (cu_i >= d.compile_unit_list.items.len) {
range_i += 1;
if (range_i >= d.ranges.items.len) {
out.* = SourceLocation.invalid;
continue :next_pc;
}
cu = &d.compile_unit_list.items[cu_i];
line_table_i = 0;
range = cu.pc_range orelse {
out.* = SourceLocation.invalid;
continue :next_pc;
};
range = &d.ranges.items[range_i];
}
if (pc < range.start) {
out.* = SourceLocation.invalid;
continue :next_pc;
}
if (line_table_i == 0) {
line_table_i = 1;
cov.mutex.unlock();
defer cov.mutex.lock();
d.populateSrcLocCache(gpa, cu) catch |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => {
out.* = SourceLocation.invalid;
cu_i += 1;
if (cu_i < d.compile_unit_list.items.len) {
cu = &d.compile_unit_list.items[cu_i];
line_table_i = 0;
if (cu.pc_range) |r| range = r;
}
continue :next_pc;
},
else => |e| return e,
};
const cu = &d.compile_unit_list.items[range.compile_unit_index];
if (cu != prev_cu) {
prev_cu = cu;
if (cu.src_loc_cache == null) {
cov.mutex.unlock();
defer cov.mutex.lock();
d.populateSrcLocCache(gpa, cu) catch |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => {
out.* = SourceLocation.invalid;
continue :next_pc;
},
else => |e| return e,
};
}
const slc = &cu.src_loc_cache.?;
const table_addrs = slc.line_table.keys();
line_table_i = std.sort.upperBound(u64, table_addrs, pc, struct {
fn order(context: u64, item: u64) std.math.Order {
return std.math.order(item, context);
}
}.order);
}
const slc = &cu.src_loc_cache.?;
const table_addrs = slc.line_table.keys();
while (line_table_i < table_addrs.len and table_addrs[line_table_i] < pc) line_table_i += 1;
while (line_table_i < table_addrs.len and table_addrs[line_table_i] <= pc) line_table_i += 1;

const entry = slc.line_table.values()[line_table_i - 1];
const corrected_file_index = entry.file - @intFromBool(slc.version < 5);
Expand Down
Loading

0 comments on commit b7a1ef3

Please sign in to comment.