-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Sanitizers] Add Driver/Frontend option to enable sanitizer instrumentation that supports error recovery #28126
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
Conversation
61a5477
to
7426a79
Compare
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.
This comes with tests for: driver, IRGen, and full integration-style execution tests. Good work!
LGTM. Let's also get approval from the Swift folks.
HelpText<"Specify which sanitizer runtime checks (see -sanitize=) will " | ||
"generate instrumentation that allows error recovery. Listed " | ||
"checks should be comma separated. Default behavior is to not " | ||
"allow error recovery.">; |
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.
How should I understand this flag compared to e.g. tsan's halt_on_error=0
? If I set sanitize-recover=address
does it unconditionally recover or can I say ASAN_OPTIONS= halt_on_error=1
?
You mentioned it only supports asan, but isn't this the default behaviour for tsan? Or is this somehow different from what tsan is doing?
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.
Good questions.
The halt_on_error
flag is actually not TSan specific. The other sanitizers have it too.
If I set sanitize-recover=address does it unconditionally recover or can I say ASAN_OPTIONS= halt_on_error=1?
No, it does not unconditionally recover. What it does is cause ASan's instrumentation to allow for error recovery. The runtime halt_on_error
option is used to decide what to do when ASan detects an issue.
Today, setting ASAN_OPTIONS=halt_on_error=0
doesn't always work. If you compile without the -sanitize-recover=address
option (equivalent to the current behavior of the swift compiler) then the generated instrumentation doesn't allow for error recovery. What this means is that if you set ASAN_OPTIONS=halt_on_error=0
at runtime and if an ASan issue is caught via instrumentation then the process will always halt regardless of how halt_on_error
is set. However, if ASan catches an issue via one of its interceptors (e.g. memcpy) then halt_on_error
runtime option is respected.
With -sanitize-recover=address
the generated instrumentation allows for error recovery which means that the halt_on_error
runtime option always does what you would expect.
ASan's default for halt_on_error
is true which means this issue only effects people who choose to not use the default behavior.
You mentioned it only supports asan, but isn't this the default behaviour for tsan? Or is this somehow different from what tsan is doing?
halt_on_error
defaults to false for TSan. The difference here is that TSan's instrumentation pass always allows for error recovery but ASan's instrumentation pass does not.
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.
Thanks for the explanation! Any reason not to accept -sanitize-recover=thread
then for consistency?
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.
Well, the flag wouldn't do anything. The ThreadSanitizer pass doesn't have an option to change the instrumentation so there's nothing we can change in the compilation process. It seems odd to me to have a driver/frontend option that doesn't effect the compilation process.
Given that we're adding a new option I'd prefer to limit the ways in which it can be used.
7426a79
to
2b24b47
Compare
@swift-ci Please smoke test |
Interesting. The test doesn't seem to work on Linux
Apart from the Linker complaining (@kubamracek @yln should I worry about this?) it looks like on Linux the symbolized source location is the full path rather than just the filename. That should be easy to fix. |
2b24b47
to
08ffc91
Compare
@swift-ci Please smoke test |
Linker: I don't understand what this means, but I think we can ignore it for this PR. |
Well something similar: |
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.
I have some questions and ideas, but if none of them are valid, I think this is fine as is.
@@ -71,6 +71,10 @@ ERROR(error_option_requires_sanitizer, none, | |||
"option '%0' requires a sanitizer to be enabled. Use -sanitize= to " | |||
"enable a sanitizer", (StringRef)) | |||
|
|||
ERROR(error_option_requires_specific_sanitizer, none, | |||
"option '%0' requires '%1' sanitizer to be enabled. Use -sanitize=%1 to " | |||
"enable the sanitizer", (StringRef, StringRef)) |
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.
Why not automatically enable the matching sanitizer?
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.
Two reasons
- Using
-sanitize-recover=address
without-sanitize=address
is a mistake in the build system and we should catch that. - Clang doesn't automatically enable a sanitizer when provided
-fsanitize-recover=address
either. It doesn't produce an error though, but I think producing an error here is better.
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.
@brentdax I've actually changed my mind here. After thinking about this some more I realised there's a legitimate use case where passing -sanitize-recover=address
without -sanitize=address
should not result in an error. Consider a scenario where -sanitize-recover=address
is globally passed to the build of a project but -sanitize-recover=address
is not enabled everywhere in the project (e.g. project is being incrementally ported to support ASan). The current version of this PR would cause a compiler error which is unhelpful. Instead I'm going to make this a warning.
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.
I've made this a warning now.
…tation that supports error recovery. The new option `-sanitize-recover=` takes a list of sanitizers that recovery instrumentation should be enabled for. Currently we only support it for Address Sanitizer. If the option is not specified then the generated instrumentation does not allow error recovery. This option mirrors the `-fsanitize-recover=` option of Clang. We don't enable recoverable instrumentation by default because it may lead to code size blow up (control flow has to be resumable). The motivation behind this change is that today, setting `ASAN_OPTIONS=halt_on_error=0` at runtime doesn't always work. If you compile without the `-sanitize-recover=address` option (equivalent to the current behavior of the swift compiler) then the generated instrumentation doesn't allow for error recovery. What this means is that if you set `ASAN_OPTIONS=halt_on_error=0` at runtime and if an ASan issue is caught via instrumentation then the process will always halt regardless of how `halt_on_error` is set. However, if ASan catches an issue via one of its interceptors (e.g. memcpy) then `the halt_on_error` runtime option is respected. With `-sanitize-recover=address` the generated instrumentation allows for error recovery which means that the `halt_on_error` runtime option is also respected when the ASan issue is caught by instrumentation. ASan's default for `halt_on_error` is true which means this issue only effects people who choose to not use the default behavior. rdar://problem/56346688
08ffc91
to
63e7290
Compare
@swift-ci Please smoke test |
// We need to test reads via instrumentation not via runtime so try to check | ||
// for calls to unwanted interceptor/runtime functions. | ||
// CHECK-IR-NOT: call {{.+}} @__asan_memcpy | ||
// CHECK-IR-NOT: call {{.+}} @memcpy |
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.
@brentdax Here's the check I've added.
@brentdax @benlangmuir I've done another pass other the PR and the smoke tests pass. Could I get an approval on this PR or some feedback if there are still problems that need addressing? |
The new option
-sanitize-recover=
takes a list of sanitizers thatrecovery instrumentation should be enabled for. Currently we only
support it for Address Sanitizer.
If the option is not specified then the generated instrumentation does
not allow error recovery.
This option mirrors the
-fsanitize-recover=
option of Clang.We don't enable recoverable instrumentation by default because it may
lead to code size blow up (control flow has to be resumable).
rdar://problem/56346688