1//===-- stats_client.cpp --------------------------------------------------===// 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// Sanitizer statistics gathering. Manages statistics for a module (executable 10// or DSO) and registers statistics with the process. 11// 12// This is linked into each individual modle and cannot directly use functions 13// declared in sanitizer_common. 14// 15//===----------------------------------------------------------------------===// 16 17#ifdef _WIN32 18#define WIN32_LEAN_AND_MEAN 19#include <windows.h> 20#else 21#include <dlfcn.h> 22#endif 23#include <stdint.h> 24#include <stdio.h> 25 26#include "sanitizer_common/sanitizer_internal_defs.h" 27#include "stats/stats.h" 28 29using namespace __sanitizer; 30 31namespace { 32 33void *LookupSymbolFromMain(const char *name) { 34#ifdef _WIN32 35 return reinterpret_cast<void *>(GetProcAddress(GetModuleHandle(0), name)); 36#else 37 return dlsym(RTLD_DEFAULT, name); 38#endif 39} 40 41StatModule *list; 42 43struct RegisterSanStats { 44 unsigned module_id; 45 46 RegisterSanStats() { 47 typedef unsigned (*reg_func_t)(StatModule **); 48 reg_func_t reg_func = reinterpret_cast<reg_func_t>( 49 LookupSymbolFromMain("__sanitizer_stats_register")); 50 if (reg_func) 51 module_id = reg_func(&list); 52 } 53 54 ~RegisterSanStats() { 55 typedef void (*unreg_func_t)(unsigned); 56 unreg_func_t unreg_func = reinterpret_cast<unreg_func_t>( 57 LookupSymbolFromMain("__sanitizer_stats_unregister")); 58 if (unreg_func) 59 unreg_func(module_id); 60 } 61} reg; 62 63} 64 65extern "C" void __sanitizer_stat_init(StatModule *mod) { 66 mod->next = list; 67 list = mod; 68} 69 70extern "C" void __sanitizer_stat_report(StatInfo *s) { 71 s->addr = GET_CALLER_PC(); 72#if defined(_WIN64) && !defined(__clang__) 73 uptr old_data = InterlockedIncrement64(reinterpret_cast<LONG64 *>(&s->data)); 74#elif defined(_WIN32) && !defined(__clang__) 75 uptr old_data = InterlockedIncrement(&s->data); 76#else 77 uptr old_data = __sync_fetch_and_add(&s->data, 1); 78#endif 79 80 // Overflow check. 81 if (CountFromData(old_data + 1) == 0) 82 Trap(); 83} 84