Cool, interesting benchmarks!
I have never ever looked at the guts of llvm; but looks like the basic
missing piece would be just emitting the forkserver init bits at entry
point; I'm assuming this is something analogous to the *_rt.c
destructors you have?
Do you mind if I put it into experimental/ for afl?
Another major benefit of doing it this way would be having
CPU-agnostic instrumentation (with the init stuff rewritten as C).
I'll probably play with it this weekend.
I think it would be also nice to allocate __afl_area_ptr if SHM setup
fails, so that the binary can be run / debugged outside afl-showmap &
related tools.
The one problem I did notice with the prototype is that if you have
other __attribute__((constructor)) functions in the compiled code,
they will execute before the _rt shim and always segfault :-/
Hm, actually, re-reading my old notes, I think this was yielding just
around 10%, at the increased risk of getting into trouble when bumping
into other mappings. So maybe not really worth it in the old code.
Another major benefit of doing it this way would be having
CPU-agnostic instrumentation (with the init stuff rewritten as C).
I'll probably play with it this weekend.
/mz
--
You received this message because you are subscribed to the Google Groups "afl-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to afl-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "afl-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to afl-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
> That would change the "semantics" of the instrumentation, which might
> be a problem.
The semantics will only improve (from probabilistic to strict).
The only problem I see is with SIGKILL, where we will fail to
synchronize with shmem at exit.
We can overcome this too: have large enough (e.g. N * 64K) global
variable for counters that will be used for the whole program,
and map each of the N 64K chunks to AFL's shmem when in AFL mode (when
used w/o afl, the counters will be distinct).
It may cost one extra indirection in instrumentation (can't see right
now how to avoid it w/o LTO and I don't want to depend on LTO here).
> I think it would be better to just keep the afl-style
> instrumentation, which is independent from the current "-fsanitize-coverage"
> passes and just include it under -fsanitize-coverage=afl or something.
It can be done, but I am reluctant to accept this into SanitizerCoverage.cpp.
As I've said before, AFL-style coverage is done the way it's done not
because it is optimal, but because
of the restrictions of the asm instrumentation which can not create new edges.
We can and should do better in a compiler.
2) no need for synchronization between instrumented modules and shared libraries. Another benefit of the simple and elegant design of "AFL-style" for instance, is that it doesn't need any special instrumentation to cover function call edges, while the ASAN-style does need one.
The performance overhead of the same styles are actually the same too. In my previous e-mail I was comparing the overhead of the AFL instrumentation to the "simple ASAN-style pass" I attached, which just breaks critical edges to get basic branch coverage, but doesn't deal with function calls (equivalent of -fsanitize-coverage=3). A more fair comparison is with the -fsanitize-coverage=4 (with additional calleer-callee coverage). The average overhead of AFL and -fsanitize-coverage=4 is basically identical: they are both ~65%, measured on SPEC2006.
So I believe both "styles" have their own benefits and it would make a lot of sense for AFL to support arbitrary size bitmaps and for -fsanitize-coverage to support fixed size bitmaps. Imagine you have a target with source code, but it uses a binary only library. Instrumenting the binary library with something more complex than afl-style would be hard, but you can do it on the assembly level for the binary and on the IR level for the main program in a compatible way. (and you need to keep the semantics for that.) To make the fixed size counter map more generic, we could have an optional multiplier for the size of the map, so you could get precision for larger programs e.g. with (n=2)*64k, while keeping it simple.So, in order to have mutual support, I'd still suggest adding the fixed sized counter map support under -fsanitize-coverage=afl or similar as it is now, extended with the optional multiplier. This would also eliminate those complications with SIGKILL, LTO and the others you've mentioned. (But again, you might have a better mapping function.) And AFL could get guaranteed precision with the support of arbitrary size counter maps. There wouldn't be complications here either, the ASAN instrumented binary could just report the correct map size to AFL before creating the SHM. I'm happy to help with patches both ways. :)
What do you think?Thanks,Laszlo
--