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