1 //===-- msan_chained_origin_depot.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 // A storage for chained origins.
11 //===----------------------------------------------------------------------===//
12
13 #include "msan_chained_origin_depot.h"
14
15 #include "sanitizer_common/sanitizer_stackdepotbase.h"
16
17 namespace __msan {
18
19 struct ChainedOriginDepotDesc {
20 u32 here_id;
21 u32 prev_id;
hash__msan::ChainedOriginDepotDesc22 u32 hash() const {
23 const u32 m = 0x5bd1e995;
24 const u32 seed = 0x9747b28c;
25 const u32 r = 24;
26 u32 h = seed;
27 u32 k = here_id;
28 k *= m;
29 k ^= k >> r;
30 k *= m;
31 h *= m;
32 h ^= k;
33
34 k = prev_id;
35 k *= m;
36 k ^= k >> r;
37 k *= m;
38 h *= m;
39 h ^= k;
40
41 h ^= h >> 13;
42 h *= m;
43 h ^= h >> 15;
44 return h;
45 }
is_valid__msan::ChainedOriginDepotDesc46 bool is_valid() { return true; }
47 };
48
49 struct ChainedOriginDepotNode {
50 ChainedOriginDepotNode *link;
51 u32 id;
52 u32 here_id;
53 u32 prev_id;
54
55 typedef ChainedOriginDepotDesc args_type;
eq__msan::ChainedOriginDepotNode56 bool eq(u32 hash, const args_type &args) const {
57 return here_id == args.here_id && prev_id == args.prev_id;
58 }
storage_size__msan::ChainedOriginDepotNode59 static uptr storage_size(const args_type &args) {
60 return sizeof(ChainedOriginDepotNode);
61 }
store__msan::ChainedOriginDepotNode62 void store(const args_type &args, u32 other_hash) {
63 here_id = args.here_id;
64 prev_id = args.prev_id;
65 }
load__msan::ChainedOriginDepotNode66 args_type load() const {
67 args_type ret = {here_id, prev_id};
68 return ret;
69 }
70 struct Handle {
71 ChainedOriginDepotNode *node_;
Handle__msan::ChainedOriginDepotNode::Handle72 Handle() : node_(0) {}
Handle__msan::ChainedOriginDepotNode::Handle73 explicit Handle(ChainedOriginDepotNode *node) : node_(node) {}
valid__msan::ChainedOriginDepotNode::Handle74 bool valid() { return node_; }
id__msan::ChainedOriginDepotNode::Handle75 u32 id() { return node_->id; }
here_id__msan::ChainedOriginDepotNode::Handle76 int here_id() { return node_->here_id; }
prev_id__msan::ChainedOriginDepotNode::Handle77 int prev_id() { return node_->prev_id; }
78 };
get_handle__msan::ChainedOriginDepotNode79 Handle get_handle() { return Handle(this); }
80
81 typedef Handle handle_type;
82 };
83
84 // kTabSizeLog = 22 => 32Mb static storage for bucket pointers.
85 static StackDepotBase<ChainedOriginDepotNode, 3, 20> chainedOriginDepot;
86
ChainedOriginDepotGetStats()87 StackDepotStats *ChainedOriginDepotGetStats() {
88 return chainedOriginDepot.GetStats();
89 }
90
ChainedOriginDepotPut(u32 here_id,u32 prev_id,u32 * new_id)91 bool ChainedOriginDepotPut(u32 here_id, u32 prev_id, u32 *new_id) {
92 ChainedOriginDepotDesc desc = {here_id, prev_id};
93 bool inserted;
94 ChainedOriginDepotNode::Handle h = chainedOriginDepot.Put(desc, &inserted);
95 *new_id = h.valid() ? h.id() : 0;
96 return inserted;
97 }
98
99 // Retrieves a stored stack trace by the id.
ChainedOriginDepotGet(u32 id,u32 * other)100 u32 ChainedOriginDepotGet(u32 id, u32 *other) {
101 ChainedOriginDepotDesc desc = chainedOriginDepot.Get(id);
102 *other = desc.prev_id;
103 return desc.here_id;
104 }
105
106 } // namespace __msan
107