Function body instrumentation

Hi :smiley:

I’m trying to transfer every function from this:

pub fn main() u8 {
    return 4;
}

to this:

pub fn main() u8 {
    @import("builtin").fuzzStackContext ^= 123;
    defer @import("builtin").fuzzStackContext ^= 123;
    return 4;
}

by patching Sema.zig.

Adding a builtin variable was easy.

the plan then was to find the place where function bodies are analyzed and emit some extra instructions there. But after a couple of hours, i still can’t find the right place. I have looked at zirFunc, sema.funcCommon, resolveGenericBody, sema.resolveInlineBody, sema.finishFunc, … but without luck.

The usecase is an implementation of the angora fuzzer for zig.

If anybody has any hints i would very much appreciate it! :smiley:

1 Like

I while back, I was wondering if I could do Aspect Oriented Programming stuff in Zig. I don’t know if this will suit your use case, but it works:

const std = @import("std");

fn ReturnType(func: anytype) type {
    return @typeInfo(@TypeOf(func)).Fn.return_type.?;
}

fn aop(func: anytype, args: anytype) ReturnType(func) {
    std.debug.print("Before\n", .{});
    defer std.debug.print("After\n", .{});
    return @call(.auto, func, args);
}

fn add(a: u8, b: u8) u8 {
    std.debug.print("add({}, {}) == {}\n", .{ a, b, a + b });
    return a + b;
}

pub fn main() !void {
    std.debug.print("{}\n", .{aop(add, .{ 1, 2 })});
}

Output

Before
add(1, 2) == 3
After
3
1 Like

That is neat but I want to instrument all functions that go into the binary automatically. I dont think zig can do that in userspace.