xref: /llvm-project/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp (revision 7c41b5ccdcf0f5de1b9b254693635283faff3658)
1ce0c41cbSdavidtrevelyan //===--- rtsan_diagnostics.cpp - Realtime Sanitizer -------------*- C++ -*-===//
2ce0c41cbSdavidtrevelyan //
3ce0c41cbSdavidtrevelyan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ce0c41cbSdavidtrevelyan // See https://llvm.org/LICENSE.txt for license information.
5ce0c41cbSdavidtrevelyan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ce0c41cbSdavidtrevelyan //
7ce0c41cbSdavidtrevelyan //===----------------------------------------------------------------------===//
8ce0c41cbSdavidtrevelyan //
9ce0c41cbSdavidtrevelyan //===----------------------------------------------------------------------===//
10ce0c41cbSdavidtrevelyan 
11ce0c41cbSdavidtrevelyan #include "rtsan/rtsan_diagnostics.h"
12ce0c41cbSdavidtrevelyan 
13ce0c41cbSdavidtrevelyan #include "sanitizer_common/sanitizer_flags.h"
14ce0c41cbSdavidtrevelyan #include "sanitizer_common/sanitizer_report_decorator.h"
15ce0c41cbSdavidtrevelyan #include "sanitizer_common/sanitizer_stacktrace.h"
16ce0c41cbSdavidtrevelyan 
17ce0c41cbSdavidtrevelyan using namespace __sanitizer;
18ce0c41cbSdavidtrevelyan using namespace __rtsan;
19ce0c41cbSdavidtrevelyan 
20ce0c41cbSdavidtrevelyan // We must define our own implementation of this method for our runtime.
21ce0c41cbSdavidtrevelyan // This one is just copied from UBSan.
22ce0c41cbSdavidtrevelyan namespace __sanitizer {
23ce0c41cbSdavidtrevelyan void BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, void *context,
24ce0c41cbSdavidtrevelyan                                     bool request_fast, u32 max_depth) {
25ce0c41cbSdavidtrevelyan   uptr top = 0;
26ce0c41cbSdavidtrevelyan   uptr bottom = 0;
27ce0c41cbSdavidtrevelyan   GetThreadStackTopAndBottom(false, &top, &bottom);
28ce0c41cbSdavidtrevelyan   bool fast = StackTrace::WillUseFastUnwind(request_fast);
29ce0c41cbSdavidtrevelyan   Unwind(max_depth, pc, bp, context, top, bottom, fast);
30ce0c41cbSdavidtrevelyan }
31ce0c41cbSdavidtrevelyan } // namespace __sanitizer
32ce0c41cbSdavidtrevelyan 
33ce0c41cbSdavidtrevelyan namespace {
34e069434aSChris Apple class Decorator : public SanitizerCommonDecorator {
35ce0c41cbSdavidtrevelyan public:
36ce0c41cbSdavidtrevelyan   Decorator() : SanitizerCommonDecorator() {}
371b601938SChris Apple   const char *FunctionName() const { return Green(); }
381b601938SChris Apple   const char *Reason() const { return Blue(); }
39ce0c41cbSdavidtrevelyan };
40ce0c41cbSdavidtrevelyan } // namespace
41ce0c41cbSdavidtrevelyan 
42*7c41b5ccSChris Apple static const char *GetErrorTypeStr(const DiagnosticsInfo &info) {
43216e1b90Sdavidtrevelyan   switch (info.type) {
44216e1b90Sdavidtrevelyan   case DiagnosticsInfoType::InterceptedCall:
45216e1b90Sdavidtrevelyan     return "unsafe-library-call";
46216e1b90Sdavidtrevelyan   case DiagnosticsInfoType::BlockingCall:
47216e1b90Sdavidtrevelyan     return "blocking-call";
48216e1b90Sdavidtrevelyan   }
49*7c41b5ccSChris Apple   CHECK(false);
50216e1b90Sdavidtrevelyan   return "(unknown error)";
51*7c41b5ccSChris Apple }
52*7c41b5ccSChris Apple 
53*7c41b5ccSChris Apple static void PrintError(const Decorator &decorator,
54*7c41b5ccSChris Apple                        const DiagnosticsInfo &info) {
551b601938SChris Apple 
561b601938SChris Apple   Printf("%s", decorator.Error());
57*7c41b5ccSChris Apple   Report("ERROR: RealtimeSanitizer: %s\n", GetErrorTypeStr(info));
581b601938SChris Apple }
591b601938SChris Apple 
601b601938SChris Apple static void PrintReason(const Decorator &decorator,
61216e1b90Sdavidtrevelyan                         const DiagnosticsInfo &info) {
621b601938SChris Apple   Printf("%s", decorator.Reason());
631b601938SChris Apple 
64216e1b90Sdavidtrevelyan   switch (info.type) {
65216e1b90Sdavidtrevelyan   case DiagnosticsInfoType::InterceptedCall: {
661b601938SChris Apple     Printf("Intercepted call to real-time unsafe function "
671b601938SChris Apple            "`%s%s%s` in real-time context!",
68216e1b90Sdavidtrevelyan            decorator.FunctionName(), info.func_name, decorator.Reason());
69216e1b90Sdavidtrevelyan     break;
70216e1b90Sdavidtrevelyan   }
71216e1b90Sdavidtrevelyan   case DiagnosticsInfoType::BlockingCall: {
721b601938SChris Apple     Printf("Call to blocking function "
731b601938SChris Apple            "`%s%s%s` in real-time context!",
74216e1b90Sdavidtrevelyan            decorator.FunctionName(), info.func_name, decorator.Reason());
75216e1b90Sdavidtrevelyan     break;
76216e1b90Sdavidtrevelyan   }
77216e1b90Sdavidtrevelyan   }
781b601938SChris Apple 
791b601938SChris Apple   Printf("\n");
801b601938SChris Apple }
811b601938SChris Apple 
821b601938SChris Apple void __rtsan::PrintDiagnostics(const DiagnosticsInfo &info) {
83*7c41b5ccSChris Apple   ScopedErrorReportLock::CheckLocked();
84ce0c41cbSdavidtrevelyan 
85ce0c41cbSdavidtrevelyan   Decorator d;
86216e1b90Sdavidtrevelyan   PrintError(d, info);
87216e1b90Sdavidtrevelyan   PrintReason(d, info);
88ce0c41cbSdavidtrevelyan   Printf("%s", d.Default());
89ce0c41cbSdavidtrevelyan }
90*7c41b5ccSChris Apple 
91*7c41b5ccSChris Apple void __rtsan::PrintErrorSummary(const DiagnosticsInfo &info,
92*7c41b5ccSChris Apple                                 const BufferedStackTrace &stack) {
93*7c41b5ccSChris Apple   ScopedErrorReportLock::CheckLocked();
94*7c41b5ccSChris Apple   ReportErrorSummary(GetErrorTypeStr(info), &stack);
95*7c41b5ccSChris Apple }
96