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