xref: /llvm-project/compiler-rt/lib/ubsan/ubsan_monitor.cpp (revision 4a3748769a5eeee13496cbffed6cc850e9b3f31e)
146ba9697SNico Weber //===-- ubsan_monitor.cpp ---------------------------------------*- C++ -*-===//
246ba9697SNico Weber //
346ba9697SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446ba9697SNico Weber // See https://llvm.org/LICENSE.txt for license information.
546ba9697SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646ba9697SNico Weber //
746ba9697SNico Weber //===----------------------------------------------------------------------===//
846ba9697SNico Weber //
946ba9697SNico Weber // Hooks which allow a monitor process to inspect UBSan's diagnostics.
1046ba9697SNico Weber //
1146ba9697SNico Weber //===----------------------------------------------------------------------===//
1246ba9697SNico Weber 
1346ba9697SNico Weber #include "ubsan_monitor.h"
1446ba9697SNico Weber 
1546ba9697SNico Weber using namespace __ubsan;
1646ba9697SNico Weber 
UndefinedBehaviorReport(const char * IssueKind,Location & Loc,InternalScopedString & Msg)1746ba9697SNico Weber UndefinedBehaviorReport::UndefinedBehaviorReport(const char *IssueKind,
1846ba9697SNico Weber                                                  Location &Loc,
1946ba9697SNico Weber                                                  InternalScopedString &Msg)
20e0dadf3dSVitaly Buka     : IssueKind(IssueKind), Loc(Loc) {
2146ba9697SNico Weber   // We have the common sanitizer reporting lock, so it's safe to register a
2246ba9697SNico Weber   // new UB report.
2346ba9697SNico Weber   RegisterUndefinedBehaviorReport(this);
2446ba9697SNico Weber 
2546ba9697SNico Weber   // Make a copy of the diagnostic.
26*4a374876SVitaly Buka   if (Msg.length())
27*4a374876SVitaly Buka     Buffer.Append(Msg.data());
2846ba9697SNico Weber 
2946ba9697SNico Weber   // Let the monitor know that a report is available.
3046ba9697SNico Weber   __ubsan_on_report();
3146ba9697SNico Weber }
3246ba9697SNico Weber 
3346ba9697SNico Weber static UndefinedBehaviorReport *CurrentUBR;
3446ba9697SNico Weber 
RegisterUndefinedBehaviorReport(UndefinedBehaviorReport * UBR)3546ba9697SNico Weber void __ubsan::RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR) {
3646ba9697SNico Weber   CurrentUBR = UBR;
3746ba9697SNico Weber }
3846ba9697SNico Weber 
3946ba9697SNico Weber SANITIZER_WEAK_DEFAULT_IMPL
__ubsan_on_report(void)4046ba9697SNico Weber void __ubsan::__ubsan_on_report(void) {}
4146ba9697SNico Weber 
__ubsan_get_current_report_data(const char ** OutIssueKind,const char ** OutMessage,const char ** OutFilename,unsigned * OutLine,unsigned * OutCol,char ** OutMemoryAddr)4246ba9697SNico Weber void __ubsan::__ubsan_get_current_report_data(const char **OutIssueKind,
4346ba9697SNico Weber                                               const char **OutMessage,
4446ba9697SNico Weber                                               const char **OutFilename,
4546ba9697SNico Weber                                               unsigned *OutLine,
4646ba9697SNico Weber                                               unsigned *OutCol,
4746ba9697SNico Weber                                               char **OutMemoryAddr) {
4846ba9697SNico Weber   if (!OutIssueKind || !OutMessage || !OutFilename || !OutLine || !OutCol ||
4946ba9697SNico Weber       !OutMemoryAddr)
5046ba9697SNico Weber     UNREACHABLE("Invalid arguments passed to __ubsan_get_current_report_data");
5146ba9697SNico Weber 
5246ba9697SNico Weber   InternalScopedString &Buf = CurrentUBR->Buffer;
5346ba9697SNico Weber 
5446ba9697SNico Weber   // Ensure that the first character of the diagnostic text can't start with a
5546ba9697SNico Weber   // lowercase letter.
56f5e6182cSVitaly Buka   char FirstChar = *Buf.data();
5746ba9697SNico Weber   if (FirstChar >= 'a' && FirstChar <= 'z')
589adc9073SVitaly Buka     *Buf.data() += 'A' - 'a';
5946ba9697SNico Weber 
6046ba9697SNico Weber   *OutIssueKind = CurrentUBR->IssueKind;
6146ba9697SNico Weber   *OutMessage = Buf.data();
6246ba9697SNico Weber   if (!CurrentUBR->Loc.isSourceLocation()) {
6346ba9697SNico Weber     *OutFilename = "<unknown>";
6446ba9697SNico Weber     *OutLine = *OutCol = 0;
6546ba9697SNico Weber   } else {
6646ba9697SNico Weber     SourceLocation SL = CurrentUBR->Loc.getSourceLocation();
6746ba9697SNico Weber     *OutFilename = SL.getFilename();
6846ba9697SNico Weber     *OutLine = SL.getLine();
6946ba9697SNico Weber     *OutCol = SL.getColumn();
7046ba9697SNico Weber   }
7146ba9697SNico Weber 
7246ba9697SNico Weber   if (CurrentUBR->Loc.isMemoryLocation())
7346ba9697SNico Weber     *OutMemoryAddr = (char *)CurrentUBR->Loc.getMemoryLocation();
7446ba9697SNico Weber   else
7546ba9697SNico Weber     *OutMemoryAddr = nullptr;
7646ba9697SNico Weber }
77