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