Dmitry Vyukov | f479287 | 2012-08-30 10:02:48 +0000 | [diff] [blame] | 1 | //===-- sanitizer_stackdepot.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 | // This file is shared between AddressSanitizer and ThreadSanitizer |
| 11 | // run-time libraries. |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "sanitizer_stackdepot.h" |
| 15 | #include "sanitizer_common.h" |
| 16 | #include "sanitizer_mutex.h" |
| 17 | |
| 18 | namespace __sanitizer { |
| 19 | |
| 20 | struct StackDesc { |
| 21 | StackDesc *link; |
| 22 | u32 id; |
| 23 | uptr hash; |
| 24 | uptr size; |
| 25 | uptr stack[1]; |
| 26 | }; |
| 27 | |
| 28 | static struct { |
| 29 | StaticSpinMutex mtx; |
| 30 | StackDesc *head; |
| 31 | u8 *region_pos; |
| 32 | u8 *region_end; |
| 33 | u32 seq; |
| 34 | } depot; |
| 35 | |
Dmitry Vyukov | 191f2f7 | 2012-08-30 13:02:30 +0000 | [diff] [blame] | 36 | static uptr hash(const uptr *stack, uptr size) { |
Dmitry Vyukov | f479287 | 2012-08-30 10:02:48 +0000 | [diff] [blame] | 37 | return 0; |
| 38 | } |
| 39 | |
| 40 | static StackDesc *allocDesc(uptr size) { |
| 41 | uptr memsz = sizeof(StackDesc) + (size - 1) * sizeof(uptr); |
| 42 | if (depot.region_pos + memsz > depot.region_end) { |
| 43 | uptr allocsz = 64*1024; |
| 44 | if (allocsz < memsz) |
| 45 | allocsz = memsz; |
| 46 | depot.region_pos = (u8*)MmapOrDie(allocsz, "stack depot"); |
| 47 | depot.region_end = depot.region_pos + allocsz; |
| 48 | } |
| 49 | StackDesc *s = (StackDesc*)depot.region_pos; |
| 50 | depot.region_pos += memsz; |
| 51 | return s; |
| 52 | } |
| 53 | |
Dmitry Vyukov | 191f2f7 | 2012-08-30 13:02:30 +0000 | [diff] [blame] | 54 | u32 StackDepotPut(const uptr *stack, uptr size) { |
Dmitry Vyukov | f479287 | 2012-08-30 10:02:48 +0000 | [diff] [blame] | 55 | if (stack == 0 || size == 0) |
| 56 | return 0; |
| 57 | uptr h = hash(stack, size); |
| 58 | SpinMutexLock l(&depot.mtx); |
| 59 | for (StackDesc *s = depot.head; s; s = s->link) { |
| 60 | if (s->hash == h && s->size == size |
| 61 | && internal_memcmp(s->stack, stack, size * sizeof(uptr)) == 0) |
| 62 | return s->id; |
| 63 | } |
| 64 | StackDesc *s = allocDesc(size); |
| 65 | s->id = ++depot.seq; |
| 66 | s->hash = h; |
| 67 | s->size = size; |
| 68 | internal_memcpy(s->stack, stack, size * sizeof(uptr)); |
| 69 | s->link = depot.head; |
| 70 | depot.head = s; |
| 71 | return s->id; |
| 72 | } |
| 73 | |
Dmitry Vyukov | 191f2f7 | 2012-08-30 13:02:30 +0000 | [diff] [blame] | 74 | const uptr *StackDepotGet(u32 id, uptr *size) { |
Dmitry Vyukov | f479287 | 2012-08-30 10:02:48 +0000 | [diff] [blame] | 75 | if (id == 0) |
| 76 | return 0; |
| 77 | SpinMutexLock l(&depot.mtx); |
| 78 | for (StackDesc *s = depot.head; s; s = s->link) { |
| 79 | if (s->id == id) { |
| 80 | *size = s->size; |
| 81 | return s->stack; |
| 82 | } |
| 83 | } |
| 84 | return 0; |
| 85 | } |
| 86 | |
| 87 | } // namespace __sanitizer |