1//===-- ubsan_monitor.cpp ---------------------------------------*- 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// Hooks which allow a monitor process to inspect UBSan's diagnostics.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ubsan_monitor.h"
14
15using namespace __ubsan;
16
17UndefinedBehaviorReport::UndefinedBehaviorReport(const char *IssueKind,
18                                                 Location &Loc,
19                                                 InternalScopedString &Msg)
20    : IssueKind(IssueKind), Loc(Loc), Buffer(Msg.length() + 1) {
21  // We have the common sanitizer reporting lock, so it's safe to register a
22  // new UB report.
23  RegisterUndefinedBehaviorReport(this);
24
25  // Make a copy of the diagnostic.
26  Buffer.append("%s", Msg.data());
27
28  // Let the monitor know that a report is available.
29  __ubsan_on_report();
30}
31
32static UndefinedBehaviorReport *CurrentUBR;
33
34void __ubsan::RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR) {
35  CurrentUBR = UBR;
36}
37
38SANITIZER_WEAK_DEFAULT_IMPL
39void __ubsan::__ubsan_on_report(void) {}
40
41void __ubsan::__ubsan_get_current_report_data(const char **OutIssueKind,
42                                              const char **OutMessage,
43                                              const char **OutFilename,
44                                              unsigned *OutLine,
45                                              unsigned *OutCol,
46                                              char **OutMemoryAddr) {
47  if (!OutIssueKind || !OutMessage || !OutFilename || !OutLine || !OutCol ||
48      !OutMemoryAddr)
49    UNREACHABLE("Invalid arguments passed to __ubsan_get_current_report_data");
50
51  InternalScopedString &Buf = CurrentUBR->Buffer;
52
53  // Ensure that the first character of the diagnostic text can't start with a
54  // lowercase letter.
55  char FirstChar = Buf.data()[0];
56  if (FirstChar >= 'a' && FirstChar <= 'z')
57    Buf.data()[0] = FirstChar - 'a' + 'A';
58
59  *OutIssueKind = CurrentUBR->IssueKind;
60  *OutMessage = Buf.data();
61  if (!CurrentUBR->Loc.isSourceLocation()) {
62    *OutFilename = "<unknown>";
63    *OutLine = *OutCol = 0;
64  } else {
65    SourceLocation SL = CurrentUBR->Loc.getSourceLocation();
66    *OutFilename = SL.getFilename();
67    *OutLine = SL.getLine();
68    *OutCol = SL.getColumn();
69  }
70
71  if (CurrentUBR->Loc.isMemoryLocation())
72    *OutMemoryAddr = (char *)CurrentUBR->Loc.getMemoryLocation();
73  else
74    *OutMemoryAddr = nullptr;
75}
76