summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_stackdepot.cc
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2014-11-06 22:49:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2014-11-06 22:49:13 +0000
commit8ef50bf3d1c287b5013c3168de77a462dfce3495 (patch)
tree3467f3372c1195b1546172d89af2205a50b1866d /lib/sanitizer_common/sanitizer_stackdepot.cc
parent11023dc647fd8f41418da90d59db138400d0f334 (diff)
Notes
Diffstat (limited to 'lib/sanitizer_common/sanitizer_stackdepot.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_stackdepot.cc34
1 files changed, 34 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_stackdepot.cc b/lib/sanitizer_common/sanitizer_stackdepot.cc
index 08e5238325e5a..2793bd0714a1e 100644
--- a/lib/sanitizer_common/sanitizer_stackdepot.cc
+++ b/lib/sanitizer_common/sanitizer_stackdepot.cc
@@ -201,4 +201,38 @@ const uptr *StackDepotGet(u32 id, uptr *size) {
return 0;
}
+bool StackDepotReverseMap::IdDescPair::IdComparator(
+ const StackDepotReverseMap::IdDescPair &a,
+ const StackDepotReverseMap::IdDescPair &b) {
+ return a.id < b.id;
+}
+
+StackDepotReverseMap::StackDepotReverseMap()
+ : map_(StackDepotGetStats()->n_uniq_ids + 100) {
+ for (int idx = 0; idx < kTabSize; idx++) {
+ atomic_uintptr_t *p = &depot.tab[idx];
+ uptr v = atomic_load(p, memory_order_consume);
+ StackDesc *s = (StackDesc*)(v & ~1);
+ for (; s; s = s->link) {
+ IdDescPair pair = {s->id, s};
+ map_.push_back(pair);
+ }
+ }
+ InternalSort(&map_, map_.size(), IdDescPair::IdComparator);
+}
+
+const uptr *StackDepotReverseMap::Get(u32 id, uptr *size) {
+ if (!map_.size()) return 0;
+ IdDescPair pair = {id, 0};
+ uptr idx = InternalBinarySearch(map_, 0, map_.size(), pair,
+ IdDescPair::IdComparator);
+ if (idx > map_.size()) {
+ *size = 0;
+ return 0;
+ }
+ StackDesc *desc = map_[idx].desc;
+ *size = desc->size;
+ return desc->stack;
+}
+
} // namespace __sanitizer