Path: blob/main/contrib/llvm-project/compiler-rt/lib/nsan/nsan_stats.cpp
35233 views
//===-- nsan_stats.cc -----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is a part of NumericalStabilitySanitizer.9//10// NumericalStabilitySanitizer statistics.11//===----------------------------------------------------------------------===//1213#include "nsan/nsan_stats.h"1415#include "sanitizer_common/sanitizer_common.h"16#include "sanitizer_common/sanitizer_placement_new.h"17#include "sanitizer_common/sanitizer_stackdepot.h"18#include "sanitizer_common/sanitizer_stacktrace.h"19#include "sanitizer_common/sanitizer_symbolizer.h"2021#include <assert.h>22#include <stdio.h>2324using namespace __sanitizer;25using namespace __nsan;2627Stats::Stats() {28check_and_warnings.Initialize(0);29TrackedLoads.Initialize(0);30}3132Stats::~Stats() { Printf("deleting nsan stats\n"); }3334static uptr Key(CheckTypeT CheckType, u32 StackId) {35return static_cast<uptr>(CheckType) +36StackId * static_cast<uptr>(CheckTypeT::kMaxCheckType);37}3839template <typename MapT, typename VectorT, typename Fn>40static void UpdateEntry(CheckTypeT check_ty, uptr pc, uptr bp, MapT *map,41VectorT *vector, Mutex *mutex, Fn F) {42BufferedStackTrace Stack;43Stack.Unwind(pc, bp, nullptr, false);44u32 stack_id = StackDepotPut(Stack);45typename MapT::Handle Handle(map, Key(check_ty, stack_id));46Lock L(mutex);47if (Handle.created()) {48typename VectorT::value_type entry;49entry.stack_id = stack_id;50entry.check_ty = check_ty;51F(entry);52vector->push_back(entry);53} else {54auto &entry = (*vector)[*Handle];55F(entry);56}57}5859void Stats::AddCheck(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {60UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,61&check_and_warning_mutex,62[rel_err](CheckAndWarningsValue &entry) {63++entry.num_checks;64if (rel_err > entry.max_relative_err) {65entry.max_relative_err = rel_err;66}67});68}6970void Stats::AddWarning(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {71UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,72&check_and_warning_mutex,73[rel_err](CheckAndWarningsValue &entry) {74++entry.num_warnings;75if (rel_err > entry.max_relative_err) {76entry.max_relative_err = rel_err;77}78});79}8081void Stats::AddInvalidLoadTrackingEvent(uptr pc, uptr bp) {82UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,83&TrackedLoadsMutex,84[](LoadTrackingValue &entry) { ++entry.num_invalid; });85}8687void Stats::AddUnknownLoadTrackingEvent(uptr pc, uptr bp) {88UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,89&TrackedLoadsMutex,90[](LoadTrackingValue &entry) { ++entry.num_unknown; });91}9293static const char *CheckTypeDisplay(CheckTypeT CheckType) {94switch (CheckType) {95case CheckTypeT::kUnknown:96return "unknown";97case CheckTypeT::kRet:98return "return";99case CheckTypeT::kArg:100return "argument";101case CheckTypeT::kLoad:102return "load";103case CheckTypeT::kStore:104return "store";105case CheckTypeT::kInsert:106return "vector insert";107case CheckTypeT::kUser:108return "user-initiated";109case CheckTypeT::kFcmp:110return "fcmp";111case CheckTypeT::kMaxCheckType:112return "[max]";113}114assert(false && "unknown CheckType case");115return "";116}117118void Stats::Print() const {119{120Lock L(&check_and_warning_mutex);121for (const auto &entry : check_and_warnings) {122Printf("warned %llu times out of %llu %s checks ", entry.num_warnings,123entry.num_checks, CheckTypeDisplay(entry.check_ty));124if (entry.num_warnings > 0) {125char RelErrBuf[64];126snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%f",127entry.max_relative_err * 100.0);128Printf("(max relative error: %s%%) ", RelErrBuf);129}130Printf("at:\n");131StackDepotGet(entry.stack_id).Print();132}133}134135{136Lock L(&TrackedLoadsMutex);137u64 TotalInvalidLoadTracking = 0;138u64 TotalUnknownLoadTracking = 0;139for (const auto &entry : TrackedLoads) {140TotalInvalidLoadTracking += entry.num_invalid;141TotalUnknownLoadTracking += entry.num_unknown;142Printf("invalid/unknown type for %llu/%llu loads at:\n",143entry.num_invalid, entry.num_unknown);144StackDepotGet(entry.stack_id).Print();145}146Printf(147"There were %llu/%llu floating-point loads where the shadow type was "148"invalid/unknown.\n",149TotalInvalidLoadTracking, TotalUnknownLoadTracking);150}151}152153alignas(64) static char stats_placeholder[sizeof(Stats)];154Stats *__nsan::nsan_stats = nullptr;155156void __nsan::InitializeStats() { nsan_stats = new (stats_placeholder) Stats(); }157158159