I am trying to reproduce a bug in the fuzzer where it fails to find a virtual address slide, I pinned the bug that it gets an address of 1 passed to from the pc-table:
// this is from `lib/fuzzer.zig` line 186
self.pc_counters = blk: {
const pc_counters_start_name = section_start_prefix ++ "__sancov_cntrs";
const pc_counters_start = @extern([*]u8, .{
.name = pc_counters_start_name,
.linkage = .weak,
}) orelse panic("missing {s} symbol", .{pc_counters_start_name});
const pc_counters_end_name = section_end_prefix ++ "__sancov_cntrs";
const pc_counters_end = @extern([*]u8, .{
.name = pc_counters_end_name,
.linkage = .weak,
}) orelse panic("missing {s} symbol", .{pc_counters_end_name});
break :blk pc_counters_start[0 .. pc_counters_end - pc_counters_start];
};
const pcs = blk: {
const pcs_start_name = section_start_prefix ++ "__sancov_pcs1";
const pcs_start = @extern([*]usize, .{
.name = pcs_start_name,
.linkage = .weak,
}) orelse panic("missing {s} symbol", .{pcs_start_name});
const pcs_end_name = section_end_prefix ++ "__sancov_pcs1";
const pcs_end = @extern([*]usize, .{
.name = pcs_end_name,
.linkage = .weak,
}) orelse panic("missing {s} symbol", .{pcs_end_name});
break :blk pcs_start[0 .. pcs_end - pcs_start];
};
if (self.pc_counters.len != pcs.len) panic(
"pc counters length and pcs length do not match ({} != {})",
.{ self.pc_counters.len, pcs.len },
);
self.pc_digest = digest: {
// Relocations have been applied to `pcs` so it contains runtime addresses (with slide
// applied). We need to translate these to the virtual addresses as on disk.
var h: std.hash.Wyhash = .init(0);
for (pcs) |pc| {
const pc_vaddr = fuzzer_unslide_address(pc);
h.update(@ptrCast(&pc_vaddr));
}
break :digest h.final();
};
self.shared_seen_pcs = getCoverageFile(cache_dir, pcs, self.pc_digest);
I tried to look through the build_runner.zig and the test_runner.zig to find how they pass around the addresses to this function but the only thing I found is this call
// this is from `lib/compiler/test_runner.zig` line 62
if (builtin.fuzz) {
const cache_dir = opt_cache_dir orelse @panic("missing --cache-dir=[path] argument");
fuzz_abi.fuzzer_init(.fromSlice(cache_dir));
}
and maybe this too could be also where the address is coming from,
// this is from `lib/std/Build/Run.zig` line 2057:
.fuzz_start_addr => {
const fuzz = fuzz_context.?.fuzz;
const addr = body_r.takeInt(u64, .little) catch unreachable;
{
fuzz.queue_mutex.lockUncancelable(io);
defer fuzz.queue_mutex.unlock(io);
try fuzz.msg_queue.append(fuzz.gpa, .{ .entry_point = .{
.addr = addr,
.coverage_id = coverage_id.?,
} });
fuzz.queue_cond.signal(io);
}
},
I wrote a program to try and reproduce this address bug
const std = @import("std");
const builtin = @import("builtin");
const native_endian = builtin.cpu.arch.endian();
const fuzz_abi = std.Build.abi.fuzz;
const Io = std.Io;
pub fn main(init: std.process.Init) !void {
_ = init;
var pc_counters: []u8 = undefined;
var pc_digest: u64 = undefined;
const ofmt = builtin.object_format;
const section_start_prefix, const section_end_prefix = switch (ofmt) {
.elf => .{ "__start__", "__stop__" },
.macho => .{ "\x01section$start$__DATA$", "\x01section$end$__DATA$" },
else => @compileError("unsupported fuzzing object format '" ++ @tagName(ofmt) ++ "'"),
};
pc_counters = blk: {
const pc_counters_start_name = section_start_prefix ++ "__sancov_cntrs";
const pc_counters_start = @extern([*]u8, .{
.name = pc_counters_start_name,
.linkage = .weak,
}) orelse std.debug.panic("missing {s} symbol", .{pc_counters_start_name});
const pc_counters_end_name = section_end_prefix ++ "__sancov_cntrs";
const pc_counters_end = @extern([*]u8, .{
.name = pc_counters_end_name,
.linkage = .weak,
}) orelse std.debug.panic("missing {s} symbol", .{pc_counters_end_name});
break :blk pc_counters_start[0 .. pc_counters_end - pc_counters_start];
};
const pcs: []usize = blk: {
const pcs_start_name = section_start_prefix ++ "__sancov_pcs1";
const pcs_start = @extern([*]usize, .{
.name = pcs_start_name,
.linkage = .weak,
}) orelse std.debug.panic("missing {s} symbol", .{pcs_start_name});
const pcs_end_name = section_end_prefix ++ "__sancov_pcs1";
const pcs_end = @extern([*]usize, .{
.name = pcs_end_name,
.linkage = .weak,
}) orelse std.debug.panic("missing {s} symbol", .{pcs_end_name});
break :blk pcs_start[0 .. pcs_end - pcs_start];
};
if (pc_counters.len != pcs.len) std.debug.panic(
"pc counters length and pcs length do not match ({} != {})",
.{ pc_counters.len, pcs.len },
);
std.log.info("pcs_len={}", .{pcs.len});
pc_digest = digest: {
var h: std.hash.Wyhash = .init(0);
for (pcs) |pc| {
std.log.info("pc=({d})", .{pc});
const pc_vaddr = fuzz_abi.fuzzer_unslide_address(pc);
h.update(@ptrCast(&pc_vaddr));
}
break :digest h.final();
};
std.log.info("{}", .{pc_digest});
}
running
$ zn run main.zig -fllvm -fsanitize-coverage-trace-pc-guard -ffuzz
I get
error: ld.lld: undefined symbol: __sanitizer_cov_trace_pc_guard
note: referenced by ubsan_rt.zig:159 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:159)
note: /home/grimtyr/.cache/zig/o/cda6d62e4406c4828aac96cb56a990f5/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced by ubsan_rt.zig:162 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:162)
note: /home/grimtyr/.cache/zig/o/cda6d62e4406c4828aac96cb56a990f5/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced by ubsan_rt.zig:162 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:162)
note: /home/grimtyr/.cache/zig/o/cda6d62e4406c4828aac96cb56a990f5/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced 20107 more times
error: ld.lld: undefined symbol: __sanitizer_cov_trace_pc_guard_init
note: referenced by main
note: /home/grimtyr/.cache/zig/o/cda6d62e4406c4828aac96cb56a990f5/main_zcu.o:(sancov.module_ctor_trace_pc_guard)
whithout -ffuzz
error: ld.lld: undefined symbol: __sanitizer_cov_trace_pc_guard
note: referenced by ubsan_rt.zig:159 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:159)
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced by ubsan_rt.zig:162 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:162)
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced by ubsan_rt.zig:162 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:162)
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced 20232 more times
error: ld.lld: undefined symbol: __sancov_lowest_stack
note: referenced by ubsan_rt.zig:159 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:159)
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced by ubsan_rt.zig:159 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:159)
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(__ubsan_handle_add_overflow)
note: referenced by ubsan_rt.zig:41 (/home/grimtyr/personal/src/zig-gt/lib/ubsan_rt.zig:41)
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(ubsan_rt.TypeDescriptor.getName)
note: referenced 3669 more times
error: ld.lld: undefined symbol: fuzzer_unslide_address
note: referenced by main.zig:61
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(main.main)
error: ld.lld: undefined symbol: __sanitizer_cov_trace_pc_guard_init
note: referenced by main
note: /home/grimtyr/.cache/zig/o/a315258bb06ca47fca799963a1fc151e/main_zcu.o:(sancov.module_ctor_trace_pc_guard)
I would like to generate the same addresses that get passed to the Executable.init function but I could not figure that part out yet
System Info
Zig Version: 0.16.0-dev.2565+684032671
Build: cmake .. -DCMAKE_BUILD_TYPE=Release -GNinja -DZIG_NO_LIB=ON
stage4: zn build -p stage4 -Denable-llvm -Dno-lib