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 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 3568d75effSDimitry Andric void __ubsan::RegisterUndefinedBehaviorReport(UndefinedBehaviorReport *UBR) { 3668d75effSDimitry Andric CurrentUBR = UBR; 3768d75effSDimitry Andric } 3868d75effSDimitry Andric 3968d75effSDimitry Andric SANITIZER_WEAK_DEFAULT_IMPL 4068d75effSDimitry Andric void __ubsan::__ubsan_on_report(void) {} 4168d75effSDimitry Andric 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