xref: /freebsd/contrib/llvm-project/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===--- rtsan_diagnostics.cpp - Realtime Sanitizer -------------*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
10*700637cbSDimitry Andric 
11*700637cbSDimitry Andric #include "rtsan/rtsan_diagnostics.h"
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "sanitizer_common/sanitizer_flags.h"
14*700637cbSDimitry Andric #include "sanitizer_common/sanitizer_report_decorator.h"
15*700637cbSDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h"
16*700637cbSDimitry Andric 
17*700637cbSDimitry Andric using namespace __sanitizer;
18*700637cbSDimitry Andric using namespace __rtsan;
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric // We must define our own implementation of this method for our runtime.
21*700637cbSDimitry Andric // This one is just copied from UBSan.
22*700637cbSDimitry Andric namespace __sanitizer {
UnwindImpl(uptr pc,uptr bp,void * context,bool request_fast,u32 max_depth)23*700637cbSDimitry Andric void BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, void *context,
24*700637cbSDimitry Andric                                     bool request_fast, u32 max_depth) {
25*700637cbSDimitry Andric   uptr top = 0;
26*700637cbSDimitry Andric   uptr bottom = 0;
27*700637cbSDimitry Andric   GetThreadStackTopAndBottom(false, &top, &bottom);
28*700637cbSDimitry Andric   bool fast = StackTrace::WillUseFastUnwind(request_fast);
29*700637cbSDimitry Andric   Unwind(max_depth, pc, bp, context, top, bottom, fast);
30*700637cbSDimitry Andric }
31*700637cbSDimitry Andric } // namespace __sanitizer
32*700637cbSDimitry Andric 
33*700637cbSDimitry Andric namespace {
34*700637cbSDimitry Andric class Decorator : public SanitizerCommonDecorator {
35*700637cbSDimitry Andric public:
Decorator()36*700637cbSDimitry Andric   Decorator() : SanitizerCommonDecorator() {}
FunctionName() const37*700637cbSDimitry Andric   const char *FunctionName() const { return Green(); }
Reason() const38*700637cbSDimitry Andric   const char *Reason() const { return Blue(); }
39*700637cbSDimitry Andric };
40*700637cbSDimitry Andric } // namespace
41*700637cbSDimitry Andric 
GetErrorTypeStr(const DiagnosticsInfo & info)42*700637cbSDimitry Andric static const char *GetErrorTypeStr(const DiagnosticsInfo &info) {
43*700637cbSDimitry Andric   switch (info.type) {
44*700637cbSDimitry Andric   case DiagnosticsInfoType::InterceptedCall:
45*700637cbSDimitry Andric     return "unsafe-library-call";
46*700637cbSDimitry Andric   case DiagnosticsInfoType::BlockingCall:
47*700637cbSDimitry Andric     return "blocking-call";
48*700637cbSDimitry Andric   }
49*700637cbSDimitry Andric   CHECK(false);
50*700637cbSDimitry Andric   return "(unknown error)";
51*700637cbSDimitry Andric }
52*700637cbSDimitry Andric 
PrintError(const Decorator & decorator,const DiagnosticsInfo & info)53*700637cbSDimitry Andric static void PrintError(const Decorator &decorator,
54*700637cbSDimitry Andric                        const DiagnosticsInfo &info) {
55*700637cbSDimitry Andric 
56*700637cbSDimitry Andric   Printf("%s", decorator.Error());
57*700637cbSDimitry Andric   Report("ERROR: RealtimeSanitizer: %s\n", GetErrorTypeStr(info));
58*700637cbSDimitry Andric }
59*700637cbSDimitry Andric 
PrintReason(const Decorator & decorator,const DiagnosticsInfo & info)60*700637cbSDimitry Andric static void PrintReason(const Decorator &decorator,
61*700637cbSDimitry Andric                         const DiagnosticsInfo &info) {
62*700637cbSDimitry Andric   Printf("%s", decorator.Reason());
63*700637cbSDimitry Andric 
64*700637cbSDimitry Andric   switch (info.type) {
65*700637cbSDimitry Andric   case DiagnosticsInfoType::InterceptedCall: {
66*700637cbSDimitry Andric     Printf("Intercepted call to real-time unsafe function "
67*700637cbSDimitry Andric            "`%s%s%s` in real-time context!",
68*700637cbSDimitry Andric            decorator.FunctionName(), info.func_name, decorator.Reason());
69*700637cbSDimitry Andric     break;
70*700637cbSDimitry Andric   }
71*700637cbSDimitry Andric   case DiagnosticsInfoType::BlockingCall: {
72*700637cbSDimitry Andric     Printf("Call to blocking function "
73*700637cbSDimitry Andric            "`%s%s%s` in real-time context!",
74*700637cbSDimitry Andric            decorator.FunctionName(), info.func_name, decorator.Reason());
75*700637cbSDimitry Andric     break;
76*700637cbSDimitry Andric   }
77*700637cbSDimitry Andric   }
78*700637cbSDimitry Andric 
79*700637cbSDimitry Andric   Printf("\n");
80*700637cbSDimitry Andric }
81*700637cbSDimitry Andric 
PrintDiagnostics(const DiagnosticsInfo & info)82*700637cbSDimitry Andric void __rtsan::PrintDiagnostics(const DiagnosticsInfo &info) {
83*700637cbSDimitry Andric   ScopedErrorReportLock::CheckLocked();
84*700637cbSDimitry Andric 
85*700637cbSDimitry Andric   Decorator d;
86*700637cbSDimitry Andric   PrintError(d, info);
87*700637cbSDimitry Andric   PrintReason(d, info);
88*700637cbSDimitry Andric   Printf("%s", d.Default());
89*700637cbSDimitry Andric }
90*700637cbSDimitry Andric 
PrintErrorSummary(const DiagnosticsInfo & info,const BufferedStackTrace & stack)91*700637cbSDimitry Andric void __rtsan::PrintErrorSummary(const DiagnosticsInfo &info,
92*700637cbSDimitry Andric                                 const BufferedStackTrace &stack) {
93*700637cbSDimitry Andric   ScopedErrorReportLock::CheckLocked();
94*700637cbSDimitry Andric   ReportErrorSummary(GetErrorTypeStr(info), &stack);
95*700637cbSDimitry Andric }
96