-
Notifications
You must be signed in to change notification settings - Fork 110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set LLVM Flag to Disable cmov (select instr) generation #380
Conversation
…t instructions (cmov) optimisations. This gives extra coverage checkpoint in && chained conditionals
This seems like a reasonable thing to do, but I haven't reviewed if this flag is the best way to go about achieving the stated goal (do you have any references we could read, even if its to LLVM source code?) |
I don't have any proof that it's the simplest way to achieve it, but essentially it's just setting a flag in the Sometimes it helps, sometimes it doesn't; but from what I've seen it never hurts the fuzzer. EDIT: perhaps this can be hidden behind a flag until you are certain that it's good? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something that we can set even when we aren't on nightly? #376 is preparing us for when sanitizers are stable in rustc. Although I suspect that if this new LLVM flag is nightly-only then the rest of them are as well.
I'd be fine merging this if we add a CLI flag like
--disable-branch-folding=true|false
with true
being the default. Ideally this would take an Option<bool>
in the clap configuration and then we can set the default to whatever we want given the rest of the config and context (e.g. we might disable it by default when running on non-nightly).
Yes, passing LLVM flags directly works on stable. In fact, the godbolt example uses the stable compiler without ever passing the -Z flag for any sanitizer. My only concern here is potential performance degradation, but it shouldn't result in additional loads or stores, so it shouldn't run into extreme slowdowns from sanitizers, and degrading performance by a single digit percentage in exchange for instrumentation that's this much better seems to be worth it. Pedantic noteThe godbolt example erroneously passes `-C opt-level=2` instead of `-C opt-level=3` to the compiler. 3 is the default for Cargo release builds. But changing it to 3 doesn't change the resulting assembly. |
As for doing this without messing with LLVM passes, our best bet is an equivalent sancov option. I couldn't find any documentation for sancov options, but at least their list is defined here: https://llvm.org/doxygen/SanitizerCoverage_8cpp_source.html I do not see anything relating to |
I only discovered this by discussing this with one of the sanitizer maintainers actually - their initial suggestion was to modify SanitizerCoverage myself... seemed overkill, but AFL++ does that here. This just seems like a much simpler option... |
Yeah, that (among other things) makes AFL++ difficult to compile and in turn difficult to use. That's why I almost entirely gave up on it in favor of using |
hmm, this doesn't do what I want:
I could rename it to |
It should be an let disable = opts.disable_branch_folding
.unwrap_or_else(|| compute_what_the_default_should_be()); |
Ok, got you 7990230 has it set to default to off (i.e. don't add the compiler flag), and 83cb30b defaults to on. Let me know which you prefer. btw, the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with one nitpick inline below, thanks!
src/options.rs
Outdated
/// A further explanation can be found here: | ||
/// https://github.com/rust-fuzz/cargo-fuzz/pull/380#issue-2445529059 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's inline the explanation here. It will be more likely to be kept up to date that way, and user's won't have to chase hyperlinks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see the latest commit; I've condensed it as much as I can, but it's definitely a long doc comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic, thanks!
Looks like there is some trailing whitespace that
Testing locally now, will get back to you in a minute. It's been a while since I ran these tests, quite possible that something on nightly changed and broke them. |
Agh, I swear I'd ran it through fmt before I committed. Just fixed that, hopefully that's all for the CI failure! |
I have nightly as my default in rustup, so I just did This is on |
I'm on EDIT: It's this I think:
EDIT 2: If it works for you, that's good enough - it seems non-trivial to install llvm-tools on macOS (with brew at least) |
btw @fitzgen, clippy has some lints when I ran it; is it worth me creating a PR to fix those?
|
I personally find that, by default, clippy is a bit too noisy for my tastes. These particular warnings all seem fine to fix. |
Hi, I work on fuzzing and I've found this flag to be useful as it breaks up conditional checks, giving coverage feedback after each check in conditionals with
&&
s (by disabling generation ofcmov
instructions - akaSelectInst
in LLVM API) . As you can imagine, having some checkpoints along the way helps the fuzzer break through complex checks. For example:becomes equivalent to this:
This link shows an example in godbolt (notice how with this flag there are 3 coverage feedback entries in the generated assembly): example
Hope this helps!