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