This is an archive of the discontinued LLVM Phabricator instance.

[compiler-rt][interception][asan][win] Improve error reporting
ClosedPublic

Authored by alvinhochun on Apr 22 2023, 11:38 AM.

Details

Summary

Add a callback from interception to allow asan on Windows to produce
better error messages. If an unrecoverable error occured when
intercepting functions, print a message before terminating.

Additionally, when encountering unknown instructions, a more helpful
message containing the address and the bytes of the unknown instruction
is now printed to help identify the issue and make it easier to propose
a fix.

Depends on D149549

Diff Detail

Event Timeline

alvinhochun created this revision.Apr 22 2023, 11:38 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 22 2023, 11:38 AM
Herald added subscribers: Enna1, dberris. · View Herald Transcript
alvinhochun requested review of this revision.Apr 22 2023, 11:38 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 22 2023, 11:38 AM
Herald added a subscriber: Restricted Project. · View Herald Transcript
vitalybuka added inline comments.Apr 27 2023, 2:27 PM
compiler-rt/lib/interception/interception_win.cpp
130

We want to avoid dependency of interceptors on most of sanitizer_common
For most users these messages is just a spam, they unlikely will rebuild and fix sanitizers.
So it's rather helpful but unnecessary debug leftovers for folks like us.

I prefer we don't land this one and dependent patch.

alvinhochun added inline comments.Apr 28 2023, 2:07 AM
compiler-rt/lib/interception/interception_win.cpp
130

The behaviour of interception_win when it encounters an unknown instruction, before this patch, is to terminate the process without printing any messages, which is very unhelpful and requires more effort than it should to diagnose. One of the changes in this patch is to make it not terminate the process, but to fail the interception like it would for any other reasons, so that if the functions it fails to intercept are not critical to the operation of asan it can still run with somewhat reduced coverage.

For most users actually these messages should not show up at all. If they show up for any users running on Windows then it means we do have a real problem that needs to be fixed. The point of these messages is, if the users file an issue with the output included it would be much easier for someone to come up with a patch because they can just check the printed instruction bytes, instead of having to debug on the affected systems.

Note that I wrote "running on Windows" -- IIRC asan-instrumented programs currently doesn't run on Wine because the functions have different instructions at the start that interception_win currently doesn't support (@mstorsjo may be able to confirm this). With this patch users can get a better idea what is wrong (or file a better bug report), and we can again fix the issues more easily with the printed bytes. Others may also start running tests on CIs under Wine and be able to report or help fix these issues in case new unsupported instructions comes up.

Also, I would really like this patch to land together with D148991. In that patch we start hooking libc++.dll and libunwind.dll for i686 MinGW. There is a chance Clang may generate different instructions and I would hate for asan to break because of it. We do have nightly checks in llvm-mingw to help catch this, and again the additional output messages can help us fix the issue more easily.

At least that's what I think. The dependency on sanitizer_common is unfortunate but I don't know how it can be avoided. Though it is only limited to Windows, can this be acceptable?

vitalybuka added inline comments.Apr 28 2023, 11:25 AM
compiler-rt/lib/interception/interception_win.cpp
130

The behavior of interception_win when it encounters an unknown instruction, before this patch, is to terminate the process without printing any messages, which is very unhelpful and requires more effort than it should to diagnose. One of the changes in this patch is to make it not terminate the process, but to fail the interception like it would for any other reasons, so that if the functions it fails to intercept are not critical to the operation of asan it can still run with somewhat reduced coverage.

This part of change LGTM.
BTW would be nice to keep Report and "make non-fatal" in separate patches.

For most users actually these messages should not show up at all. If they show up for any users running on Windows then it means we do have a real problem that needs to be fixed. The point of these messages is, if the users file an issue with the output included it would be much easier for someone to come up with a patch because they can just check the printed instruction bytes, instead of having to debug on the affected systems.

So even less reasons to introduce this dependency?

Note that I wrote "running on Windows" -- IIRC asan-instrumented programs currently doesn't run on Wine because the functions have different instructions at the start that interception_win currently doesn't support (@mstorsjo may be able to confirm this). With this patch users can get a better idea what is wrong (or file a better bug report), and we can again fix the issues more easily with the printed bytes. Others may also start running tests on CIs under Wine and be able to report or help fix these issues in case new unsupported instructions comes up.

We kind of have this functionality in llvm-project/compiler-rt/lib/asan/asan_interceptors.h:140
maybe we can extend to:

VReport(1, "AddressSanitizer: failed to intercept '%s, details: %s'\n", #name, getLastInterceptionError());

Another way to break dependency is to call from asan:

void __interception::SetOnErrorCallback(void(*)(const char*, uptr addr));
``

> 
> Also, I would really like this patch to land together with D148991. In that patch we start hooking `libc++.dll` and `libunwind.dll` for i686 MinGW. There is a chance Clang may generate different instructions and I would hate for asan to break because of it. We do have nightly checks in llvm-mingw to help catch this, and again the additional output messages can help us fix the issue more easily.
> 
> At least that's what I think. The dependency on sanitizer_common is unfortunate but I don't know how it can be avoided. Though it is only limited to Windows, can this be acceptable?

This is windows only, however there is stuff like e.g. safestack which depends on interception but not on common. I don't think we have that on Windows, but you are making this a problem for future committers who decide to support that.
compiler-rt/lib/interception/tests/CMakeLists.txt
109

maybe add gmock on all platforms to have less conditions in CMake?

alvinhochun retitled this revision from [compiler-rt][interception][win] Improve error reporting to [compiler-rt][interception][asan][win] Improve error reporting.
alvinhochun edited the summary of this revision. (Show Details)

Split the bit making unknown instructions non-fatal into D149549, and change the way errors are reported to avoid direct dependency from interception to sanitizer_common. Now asan registers a callback in interceptor to call __sanitizer::Report.

alvinhochun marked an inline comment as done.Apr 30 2023, 7:02 AM
alvinhochun added inline comments.
compiler-rt/lib/interception/tests/CMakeLists.txt
109

Now the test doesn't require gmock.

vitalybuka added inline comments.Apr 30 2023, 10:46 PM
compiler-rt/lib/asan/asan_mac.cpp
47 ↗(On Diff #518305)

Can we instead move InitializePlatformInterceptors() in to the beginning of InitializeAsanInterceptors()?

compiler-rt/lib/interception/interception_win.cpp
159–163

Can we avoid a macro?
static inline should work?

Can you call it ReportError, to avoid confusion for Report in common

alvinhochun marked an inline comment as done.May 1 2023, 1:59 AM
alvinhochun added inline comments.
compiler-rt/lib/asan/asan_mac.cpp
47 ↗(On Diff #518305)

Yeah, looks like we can do that.

compiler-rt/lib/interception/interception_win.cpp
159–163

The problem is calling a variadic function, there is no way that I know of to just forward the arguments without using va_list. There is currently not a version of __sanitizer::Report that takes va_list, so I would have to add one, which is more work than just using a macro here.

I can rename the macro to ReportError, yes.

vitalybuka added inline comments.May 1 2023, 3:44 PM
compiler-rt/lib/asan/asan_mac.cpp
47 ↗(On Diff #518305)

Marked as done, but not done?

compiler-rt/lib/interception/interception_win.cpp
159–163

This should work https://en.cppreference.com/w/cpp/language/parameter_pack

template<class... Ts>
void ReportError(Ts... args) {
      if (ErrorReportCallback)            
        ErrorReportCallback(args...); 
}
alvinhochun marked 2 inline comments as not done.May 2 2023, 12:44 AM
alvinhochun added inline comments.
compiler-rt/lib/interception/interception_win.cpp
159–163

Ah , didn't know we can do this. However, if I take this approach then we will lose the printf format check warnings provided by __attribute__((format)) (doesn't work when applied to the template function with parameter pack). I think these checks are quite worth having.

Address some comments

alvinhochun marked 4 inline comments as done.May 2 2023, 3:26 AM
vitalybuka accepted this revision.May 2 2023, 10:51 PM
vitalybuka added inline comments.
compiler-rt/lib/interception/interception_win.cpp
159–163

I don's see why is that? When template instantiated all types are known to call ErrorReportCallback

If it's broken, my preference is to rather abandon format check, as we have just a few calls. but avoid macro.

However, because it's just 2 calls, I don't see a problem
removing ReportError and inlining calls

669–670

we use lowercase for hex in sanitizers

This revision is now accepted and ready to land.May 2 2023, 10:51 PM
alvinhochun added inline comments.May 3 2023, 3:36 AM
compiler-rt/lib/interception/interception_win.cpp
159–163

Variadic arguments are converted using default argument promotions, but template arguments don't get this promotion which confuses the format checks. There are also a couple of GCC-compat warnings.

warning: GCC does not allow 'format' attribute in this position on a function definition [-Wgcc-compat]
warning: GCC requires a function with the 'format' attribute to be variadic [-Wgcc-compat]
warning: format specifies type 'unsigned int' but the argument has type 'u8' (aka 'unsigned char') [-Wformat]

I'm curious, why should we avoid this macro? VReport and VPrintf in sanitizer_common.h are similar macros, and they make use of Printf and Report which also have the format check attributes. In my opinion the alternatives to having this macro are worse. Do note that the child patch adds two more usages of ReportError.

669–670

Sure, I can change it before committing if you are fine with that.

vitalybuka requested changes to this revision.May 3 2023, 11:03 AM
vitalybuka added inline comments.
compiler-rt/lib/asan/asan_win.cpp
162 ↗(On Diff #518673)

Maybe VReport?

compiler-rt/lib/interception/interception_win.cpp
159–163

Variadic arguments are converted using default argument promotions, but template arguments don't get this promotion which confuses the format checks. There are also a couple of GCC-compat warnings.

warning: GCC does not allow 'format' attribute in this position on a function definition [-Wgcc-compat]
warning: GCC requires a function with the 'format' attribute to be variadic [-Wgcc-compat]
warning: format specifies type 'unsigned int' but the argument has type 'u8' (aka 'unsigned char') [-Wformat]

I'm curious, why should we avoid this macro? VReport and VPrintf in sanitizer_common.h are similar macros, and they make use of Printf and Report which also have the format check attributes. In my opinion the alternatives to having this macro are worse. Do note that the child patch adds two more usages of ReportError.

Reasons are harder to debug, bad stack traces, weird compilation error.
I don't see reasons to have them there as well.

Either way I don't think the issue is important, with or without macro is OK to me.

669–670

Yes, please change.

This revision now requires changes to proceed.May 3 2023, 11:03 AM
vitalybuka accepted this revision.May 3 2023, 11:04 AM
This revision is now accepted and ready to land.May 3 2023, 11:04 AM

This revision now requires changes to proceed.

Sorry, just selected wrong item

alvinhochun added inline comments.May 4 2023, 7:35 AM
compiler-rt/lib/asan/asan_win.cpp
162 ↗(On Diff #518673)

VReport is a macro so not possible. Besides, I think these messages are important enough to not require the verbosity check for now.

This revision was landed with ongoing or failed builds.May 4 2023, 7:41 AM
This revision was automatically updated to reflect the committed changes.