| Sergey Matveev | da9f5e7 | 2013-10-14 12:01:05 +0000 | [diff] [blame] | 1 | //===-- asan_posix.cc -----------------------------------------------------===// |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 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 a part of AddressSanitizer, an address sanity checker. |
| 11 | // |
| 12 | // Posix-specific details. |
| 13 | //===----------------------------------------------------------------------===// |
| Evgeniy Stepanov | 0af6723 | 2013-03-19 14:33:38 +0000 | [diff] [blame] | 14 | |
| 15 | #include "sanitizer_common/sanitizer_platform.h" |
| Alexey Samsonov | a7c602a | 2014-03-04 08:55:41 +0000 | [diff] [blame^] | 16 | #if SANITIZER_POSIX |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 17 | |
| 18 | #include "asan_internal.h" |
| 19 | #include "asan_interceptors.h" |
| Evgeniy Stepanov | 8152e22 | 2012-05-23 15:21:50 +0000 | [diff] [blame] | 20 | #include "asan_mapping.h" |
| Alexey Samsonov | aa05110 | 2012-08-09 07:40:58 +0000 | [diff] [blame] | 21 | #include "asan_report.h" |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 22 | #include "asan_stack.h" |
| Alexey Samsonov | 1b12eda | 2012-06-05 08:48:10 +0000 | [diff] [blame] | 23 | #include "sanitizer_common/sanitizer_libc.h" |
| Alexey Samsonov | 28a9895 | 2012-06-07 06:15:12 +0000 | [diff] [blame] | 24 | #include "sanitizer_common/sanitizer_procmaps.h" |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 25 | |
| Kostya Serebryany | 1dd51b5 | 2012-01-11 02:21:06 +0000 | [diff] [blame] | 26 | #include <pthread.h> |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 27 | #include <signal.h> |
| Alexey Samsonov | d665150 | 2012-02-22 14:07:06 +0000 | [diff] [blame] | 28 | #include <stdlib.h> |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 29 | #include <sys/time.h> |
| 30 | #include <sys/resource.h> |
| Kostya Serebryany | edb4a8a | 2012-01-09 23:11:26 +0000 | [diff] [blame] | 31 | #include <unistd.h> |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 32 | |
| 33 | namespace __asan { |
| 34 | |
| Alexander Potapenko | 789e3e1 | 2014-01-31 13:10:07 +0000 | [diff] [blame] | 35 | void AsanOnSIGSEGV(int, void *siginfo, void *context) { |
| 36 | uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr; |
| Evgeniy Stepanov | cba008e | 2014-02-19 13:40:41 +0000 | [diff] [blame] | 37 | int code = (int)((siginfo_t*)siginfo)->si_code; |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 38 | // Write the first message using the bullet-proof write. |
| Alexey Samsonov | c4b2013 | 2012-06-06 07:02:44 +0000 | [diff] [blame] | 39 | if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); |
| Kostya Serebryany | 8d03204 | 2012-05-31 14:35:53 +0000 | [diff] [blame] | 40 | uptr pc, sp, bp; |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 41 | GetPcSpBp(context, &pc, &sp, &bp); |
| Evgeniy Stepanov | cba008e | 2014-02-19 13:40:41 +0000 | [diff] [blame] | 42 | |
| 43 | // Access at a reasonable offset above SP, or slightly below it (to account |
| 44 | // for x86_64 redzone, ARM push of multiple registers, etc) is probably a |
| 45 | // stack overflow. |
| 46 | // We also check si_code to filter out SEGV caused by something else other |
| 47 | // then hitting the guard page or unmapped memory, like, for example, |
| 48 | // unaligned memory access. |
| 49 | if (addr + 128 > sp && addr < sp + 0xFFFF && |
| 50 | (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) |
| 51 | ReportStackOverflow(pc, sp, bp, context, addr); |
| 52 | else |
| 53 | ReportSIGSEGV(pc, sp, bp, context, addr); |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 54 | } |
| 55 | |
| Kostya Serebryany | 1dd51b5 | 2012-01-11 02:21:06 +0000 | [diff] [blame] | 56 | // ---------------------- TSD ---------------- {{{1 |
| 57 | |
| 58 | static pthread_key_t tsd_key; |
| 59 | static bool tsd_key_inited = false; |
| Kostya Serebryany | b5eb5a7 | 2012-02-07 00:27:15 +0000 | [diff] [blame] | 60 | void AsanTSDInit(void (*destructor)(void *tsd)) { |
| Kostya Serebryany | 1dd51b5 | 2012-01-11 02:21:06 +0000 | [diff] [blame] | 61 | CHECK(!tsd_key_inited); |
| 62 | tsd_key_inited = true; |
| Kostya Serebryany | 5b4267f | 2013-04-05 14:40:25 +0000 | [diff] [blame] | 63 | CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); |
| Kostya Serebryany | 1dd51b5 | 2012-01-11 02:21:06 +0000 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | void *AsanTSDGet() { |
| 67 | CHECK(tsd_key_inited); |
| 68 | return pthread_getspecific(tsd_key); |
| 69 | } |
| 70 | |
| 71 | void AsanTSDSet(void *tsd) { |
| 72 | CHECK(tsd_key_inited); |
| 73 | pthread_setspecific(tsd_key, tsd); |
| 74 | } |
| 75 | |
| Sergey Matveev | da9f5e7 | 2013-10-14 12:01:05 +0000 | [diff] [blame] | 76 | void PlatformTSDDtor(void *tsd) { |
| 77 | AsanThreadContext *context = (AsanThreadContext*)tsd; |
| 78 | if (context->destructor_iterations > 1) { |
| 79 | context->destructor_iterations--; |
| 80 | CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); |
| 81 | return; |
| 82 | } |
| 83 | AsanThread::TSDDtor(tsd); |
| 84 | } |
| Kostya Serebryany | 5be458c | 2012-01-09 19:18:27 +0000 | [diff] [blame] | 85 | } // namespace __asan |
| 86 | |
| Alexey Samsonov | a7c602a | 2014-03-04 08:55:41 +0000 | [diff] [blame^] | 87 | #endif // SANITIZER_POSIX |