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