168d75effSDimitry Andric //===-- ubsan_monitor.cpp ---------------------------------------*- C++ -*-===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // Hooks which allow a monitor process to inspect UBSan's diagnostics.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric //===----------------------------------------------------------------------===//
1268d75effSDimitry Andric
1368d75effSDimitry Andric #include "ubsan_monitor.h"
1468d75effSDimitry Andric
1568d75effSDimitry Andric using namespace __ubsan;
1668d75effSDimitry Andric
UndefinedBehaviorReport(const char * IssueKind,Location & Loc,InternalScopedString & Msg)1768d75effSDimitry Andric UndefinedBehaviorReport::UndefinedBehaviorReport(const char *IssueKind,
1868d75effSDimitry Andric Location &Loc,
1968d75effSDimitry Andric InternalScopedString &Msg)
20fe6060f1SDimitry Andric : IssueKind(IssueKind), Loc(Loc) {
2168d75effSDimitry Andric // We have the common sanitizer reporting lock, so it's safe to register a
2268d75effSDimitry Andric // new UB report.
2368d75effSDimitry Andric RegisterUndefinedBehaviorReport(this);
2468d75effSDimitry Andric
2568d75effSDimitry Andric // Make a copy of the diagnostic.
26*5f757f3fSDimitry Andric if (Msg.length())
27*5f757f3fSDimitry Andric Buffer.Append(Msg.data());
2868d75effSDimitry Andric
2968d75effSDimitry Andric // Let the monitor know that a report is available.
3068d75effSDimitry Andric __ubsan_on_report();
3168d75effSDimitry Andric }
3268d75effSDimitry Andric
3368d75effSDimitry Andric static UndefinedBehaviorReport *CurrentUBR;
3468d75effSDimitry Andric
RegisterUndefinedBehaviorReport(UndefinedBehaviorReport * UBR)3568d75effSDimitry Andric void __ubsan::RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR) {
3668d75effSDimitry Andric CurrentUBR = UBR;
3768d75effSDimitry Andric }
3868d75effSDimitry Andric
3968d75effSDimitry Andric SANITIZER_WEAK_DEFAULT_IMPL
__ubsan_on_report(void)4068d75effSDimitry Andric void __ubsan::__ubsan_on_report(void) {}
4168d75effSDimitry Andric
__ubsan_get_current_report_data(const char ** OutIssueKind,const char ** OutMessage,const char ** OutFilename,unsigned * OutLine,unsigned * OutCol,char ** OutMemoryAddr)4268d75effSDimitry Andric void __ubsan::__ubsan_get_current_report_data(const char **OutIssueKind,
4368d75effSDimitry Andric const char **OutMessage,
4468d75effSDimitry Andric const char **OutFilename,
4568d75effSDimitry Andric unsigned *OutLine,
4668d75effSDimitry Andric unsigned *OutCol,
4768d75effSDimitry Andric char **OutMemoryAddr) {
4868d75effSDimitry Andric if (!OutIssueKind || !OutMessage || !OutFilename || !OutLine || !OutCol ||
4968d75effSDimitry Andric !OutMemoryAddr)
5068d75effSDimitry Andric UNREACHABLE("Invalid arguments passed to __ubsan_get_current_report_data");
5168d75effSDimitry Andric
5268d75effSDimitry Andric InternalScopedString &Buf = CurrentUBR->Buffer;
5368d75effSDimitry Andric
5468d75effSDimitry Andric // Ensure that the first character of the diagnostic text can't start with a
5568d75effSDimitry Andric // lowercase letter.
56fe6060f1SDimitry Andric char FirstChar = *Buf.data();
5768d75effSDimitry Andric if (FirstChar >= 'a' && FirstChar <= 'z')
58fe6060f1SDimitry Andric *Buf.data() += 'A' - 'a';
5968d75effSDimitry Andric
6068d75effSDimitry Andric *OutIssueKind = CurrentUBR->IssueKind;
6168d75effSDimitry Andric *OutMessage = Buf.data();
6268d75effSDimitry Andric if (!CurrentUBR->Loc.isSourceLocation()) {
6368d75effSDimitry Andric *OutFilename = "<unknown>";
6468d75effSDimitry Andric *OutLine = *OutCol = 0;
6568d75effSDimitry Andric } else {
6668d75effSDimitry Andric SourceLocation SL = CurrentUBR->Loc.getSourceLocation();
6768d75effSDimitry Andric *OutFilename = SL.getFilename();
6868d75effSDimitry Andric *OutLine = SL.getLine();
6968d75effSDimitry Andric *OutCol = SL.getColumn();
7068d75effSDimitry Andric }
7168d75effSDimitry Andric
7268d75effSDimitry Andric if (CurrentUBR->Loc.isMemoryLocation())
7368d75effSDimitry Andric *OutMemoryAddr = (char *)CurrentUBR->Loc.getMemoryLocation();
7468d75effSDimitry Andric else
7568d75effSDimitry Andric *OutMemoryAddr = nullptr;
7668d75effSDimitry Andric }
77