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