brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 49041a7 Raw
158 lines · cpp
1//===-- nsan_stats.cc -----------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of NumericalStabilitySanitizer.10//11// NumericalStabilitySanitizer statistics.12//===----------------------------------------------------------------------===//13 14#include "nsan_stats.h"15 16#include "sanitizer_common/sanitizer_common.h"17#include "sanitizer_common/sanitizer_placement_new.h"18#include "sanitizer_common/sanitizer_stackdepot.h"19#include "sanitizer_common/sanitizer_stacktrace.h"20#include "sanitizer_common/sanitizer_symbolizer.h"21 22#include <assert.h>23#include <stdio.h>24 25using namespace __sanitizer;26using namespace __nsan;27 28Stats::Stats() {29  check_and_warnings.Initialize(0);30  TrackedLoads.Initialize(0);31}32 33Stats::~Stats() { Printf("deleting nsan stats\n"); }34 35static uptr Key(CheckTypeT CheckType, u32 StackId) {36  return static_cast<uptr>(CheckType) +37         StackId * static_cast<uptr>(CheckTypeT::kMaxCheckType);38}39 40template <typename MapT, typename VectorT, typename Fn>41static void UpdateEntry(CheckTypeT check_ty, uptr pc, uptr bp, MapT *map,42                        VectorT *vector, Mutex *mutex, Fn F) {43  BufferedStackTrace Stack;44  Stack.Unwind(pc, bp, nullptr, false);45  u32 stack_id = StackDepotPut(Stack);46  typename MapT::Handle Handle(map, Key(check_ty, stack_id));47  Lock L(mutex);48  if (Handle.created()) {49    typename VectorT::value_type entry;50    entry.stack_id = stack_id;51    entry.check_ty = check_ty;52    F(entry);53    vector->push_back(entry);54  } else {55    auto &entry = (*vector)[*Handle];56    F(entry);57  }58}59 60void Stats::AddCheck(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {61  UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,62              &check_and_warning_mutex,63              [rel_err](CheckAndWarningsValue &entry) {64                ++entry.num_checks;65                if (rel_err > entry.max_relative_err) {66                  entry.max_relative_err = rel_err;67                }68              });69}70 71void Stats::AddWarning(CheckTypeT check_ty, uptr pc, uptr bp, double rel_err) {72  UpdateEntry(check_ty, pc, bp, &CheckAndWarningsMap, &check_and_warnings,73              &check_and_warning_mutex,74              [rel_err](CheckAndWarningsValue &entry) {75                ++entry.num_warnings;76                if (rel_err > entry.max_relative_err) {77                  entry.max_relative_err = rel_err;78                }79              });80}81 82void Stats::AddInvalidLoadTrackingEvent(uptr pc, uptr bp) {83  UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,84              &TrackedLoadsMutex,85              [](LoadTrackingValue &entry) { ++entry.num_invalid; });86}87 88void Stats::AddUnknownLoadTrackingEvent(uptr pc, uptr bp) {89  UpdateEntry(CheckTypeT::kLoad, pc, bp, &LoadTrackingMap, &TrackedLoads,90              &TrackedLoadsMutex,91              [](LoadTrackingValue &entry) { ++entry.num_unknown; });92}93 94static const char *CheckTypeDisplay(CheckTypeT CheckType) {95  switch (CheckType) {96  case CheckTypeT::kUnknown:97    return "unknown";98  case CheckTypeT::kRet:99    return "return";100  case CheckTypeT::kArg:101    return "argument";102  case CheckTypeT::kLoad:103    return "load";104  case CheckTypeT::kStore:105    return "store";106  case CheckTypeT::kInsert:107    return "vector insert";108  case CheckTypeT::kUser:109    return "user-initiated";110  case CheckTypeT::kFcmp:111    return "fcmp";112  case CheckTypeT::kMaxCheckType:113    return "[max]";114  }115  assert(false && "unknown CheckType case");116  return "";117}118 119void Stats::Print() const {120  {121    Lock L(&check_and_warning_mutex);122    for (const auto &entry : check_and_warnings) {123      Printf("warned %llu times out of %llu %s checks ", entry.num_warnings,124             entry.num_checks, CheckTypeDisplay(entry.check_ty));125      if (entry.num_warnings > 0) {126        char RelErrBuf[64];127        snprintf(RelErrBuf, sizeof(RelErrBuf) - 1, "%f",128                 entry.max_relative_err * 100.0);129        Printf("(max relative error: %s%%) ", RelErrBuf);130      }131      Printf("at:\n");132      StackDepotGet(entry.stack_id).Print();133    }134  }135 136  {137    Lock L(&TrackedLoadsMutex);138    u64 TotalInvalidLoadTracking = 0;139    u64 TotalUnknownLoadTracking = 0;140    for (const auto &entry : TrackedLoads) {141      TotalInvalidLoadTracking += entry.num_invalid;142      TotalUnknownLoadTracking += entry.num_unknown;143      Printf("invalid/unknown type for %llu/%llu loads at:\n",144             entry.num_invalid, entry.num_unknown);145      StackDepotGet(entry.stack_id).Print();146    }147    Printf(148        "There were %llu/%llu floating-point loads where the shadow type was "149        "invalid/unknown.\n",150        TotalInvalidLoadTracking, TotalUnknownLoadTracking);151  }152}153 154alignas(64) static char stats_placeholder[sizeof(Stats)];155Stats *__nsan::nsan_stats = nullptr;156 157void __nsan::InitializeStats() { nsan_stats = new (stats_placeholder) Stats(); }158