blob: 88afd34ed52bd80654e7a1812403adff3ffb410e [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/ld/abi.h>
#include <lib/ubsan-custom/handlers.h>
#include "startup-diagnostics.h"
// This is set by the ld::Diagnostics constructor, so it should be set fairly
// early in StartLd. If there is a ubsan failure report before it's set, it
// will just be silent a crash.
ld::DiagnosticsReport* ld::Diagnostics::gReport_;
namespace ubsan {
namespace {
constexpr const char* ProgramName() { return ld::abi::Abi<>::kSoname.c_str(); }
} // namespace
// This (via <lib/ubsan-custom/handlers.h>) defines the custom ubsan runtime
// for the startup dynamic linker. The ubsan:: functions below handle the
// details specific to the environment: how to print and how to panic.
Report::Report(const char* check, const SourceLocation& loc, //
void* caller, void* frame) {
auto* report = ld::Diagnostics::gReport_;
if (!report) {
// Just crash immediately if no messages will get out anyway.
__builtin_trap();
return;
}
if (loc.column == 0) {
report->Printf(
"%s: %s:%u: *** "
"UndefinedBehaviorSanitizer CHECK FAILED *** %s PC {{{pc:%p}}} FP %p",
ProgramName(), loc.filename, loc.line, check, caller, frame);
} else {
report->Printf(
"%s: %s:%u:%u: *** "
"UndefinedBehaviorSanitizer CHECK FAILED *** %s PC {{{pc:%p}}} FP %p",
ProgramName(), loc.filename, loc.line, loc.column, check, caller, frame);
}
}
// **Note:** //tools/testing/tefmocheck/string_in_log_check.go matches this
// exact fragment in console logs to flag reports that should not be ignored.
// So however this message changes, make sure that this fragment remains
// identical to the precise string tefmocheck matches.
#define SUMMARY_TEXT "SUMMARY: UndefinedBehaviorSanitizer"
Report::~Report() {
// The constructor crashes if gReport_ isn't set, so it always will be here.
ld::Diagnostics::gReport_->Printf( //
"%s: *** " SUMMARY_TEXT " ERRORS! Emergency crash! ***", ProgramName());
__builtin_trap();
}
void VPrintf(const char* fmt, va_list args) {
if (auto* report = ld::Diagnostics::gReport_) {
// It's not easy to prefix with "%s: *** " and ProgramName() in a single
// formatted line, so these detail lines won't be marked that way. But the
// header and footer lines will be.
report->Printf(fmt, args);
}
}
} // namespace ubsan