blob: 57c9581120cb68acec517f58a7453beb06efec9c [file] [log] [blame]
Sergey Matveevda9f5e72013-10-14 12:01:05 +00001//===-- asan_posix.cc -----------------------------------------------------===//
Kostya Serebryany5be458c2012-01-09 19:18:27 +00002//
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 Stepanov0af67232013-03-19 14:33:38 +000014
15#include "sanitizer_common/sanitizer_platform.h"
Alexey Samsonova7c602a2014-03-04 08:55:41 +000016#if SANITIZER_POSIX
Kostya Serebryany5be458c2012-01-09 19:18:27 +000017
18#include "asan_internal.h"
19#include "asan_interceptors.h"
Evgeniy Stepanov8152e222012-05-23 15:21:50 +000020#include "asan_mapping.h"
Alexey Samsonovaa051102012-08-09 07:40:58 +000021#include "asan_report.h"
Kostya Serebryany5be458c2012-01-09 19:18:27 +000022#include "asan_stack.h"
Alexey Samsonov1b12eda2012-06-05 08:48:10 +000023#include "sanitizer_common/sanitizer_libc.h"
Alexey Samsonov28a98952012-06-07 06:15:12 +000024#include "sanitizer_common/sanitizer_procmaps.h"
Kostya Serebryany5be458c2012-01-09 19:18:27 +000025
Kostya Serebryany1dd51b52012-01-11 02:21:06 +000026#include <pthread.h>
Kostya Serebryany5be458c2012-01-09 19:18:27 +000027#include <signal.h>
Alexey Samsonovd6651502012-02-22 14:07:06 +000028#include <stdlib.h>
Kostya Serebryany5be458c2012-01-09 19:18:27 +000029#include <sys/time.h>
30#include <sys/resource.h>
Kostya Serebryanyedb4a8a2012-01-09 23:11:26 +000031#include <unistd.h>
Kostya Serebryany5be458c2012-01-09 19:18:27 +000032
33namespace __asan {
34
Alexander Potapenko789e3e12014-01-31 13:10:07 +000035void AsanOnSIGSEGV(int, void *siginfo, void *context) {
36 uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
Evgeniy Stepanovcba008e2014-02-19 13:40:41 +000037 int code = (int)((siginfo_t*)siginfo)->si_code;
Kostya Serebryany5be458c2012-01-09 19:18:27 +000038 // Write the first message using the bullet-proof write.
Alexey Samsonovc4b20132012-06-06 07:02:44 +000039 if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
Kostya Serebryany8d032042012-05-31 14:35:53 +000040 uptr pc, sp, bp;
Kostya Serebryany5be458c2012-01-09 19:18:27 +000041 GetPcSpBp(context, &pc, &sp, &bp);
Evgeniy Stepanovcba008e2014-02-19 13:40:41 +000042
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 Serebryany5be458c2012-01-09 19:18:27 +000054}
55
Kostya Serebryany1dd51b52012-01-11 02:21:06 +000056// ---------------------- TSD ---------------- {{{1
57
58static pthread_key_t tsd_key;
59static bool tsd_key_inited = false;
Kostya Serebryanyb5eb5a72012-02-07 00:27:15 +000060void AsanTSDInit(void (*destructor)(void *tsd)) {
Kostya Serebryany1dd51b52012-01-11 02:21:06 +000061 CHECK(!tsd_key_inited);
62 tsd_key_inited = true;
Kostya Serebryany5b4267f2013-04-05 14:40:25 +000063 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
Kostya Serebryany1dd51b52012-01-11 02:21:06 +000064}
65
66void *AsanTSDGet() {
67 CHECK(tsd_key_inited);
68 return pthread_getspecific(tsd_key);
69}
70
71void AsanTSDSet(void *tsd) {
72 CHECK(tsd_key_inited);
73 pthread_setspecific(tsd_key, tsd);
74}
75
Sergey Matveevda9f5e72013-10-14 12:01:05 +000076void 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 Serebryany5be458c2012-01-09 19:18:27 +000085} // namespace __asan
86
Alexey Samsonova7c602a2014-03-04 08:55:41 +000087#endif // SANITIZER_POSIX