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