]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- asan_interceptors.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 a part of AddressSanitizer, an address sanity checker. | |
11 | // | |
12 | // Interceptors for operators new and delete. | |
13 | //===----------------------------------------------------------------------===// | |
14 | ||
15 | #include "asan_allocator.h" | |
16 | #include "asan_internal.h" | |
17 | #include "asan_stack.h" | |
18 | ||
92a42be0 | 19 | #include "interception/interception.h" |
1a4d82fc JJ |
20 | |
21 | #include <stddef.h> | |
22 | ||
92a42be0 SL |
23 | // C++ operators can't have visibility attributes on Windows. |
24 | #if SANITIZER_WINDOWS | |
25 | # define CXX_OPERATOR_ATTRIBUTE | |
26 | #else | |
27 | # define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE | |
28 | #endif | |
1a4d82fc JJ |
29 | |
30 | using namespace __asan; // NOLINT | |
31 | ||
32 | // This code has issues on OSX. | |
33 | // See https://code.google.com/p/address-sanitizer/issues/detail?id=131. | |
34 | ||
35 | // Fake std::nothrow_t to avoid including <new>. | |
36 | namespace std { | |
37 | struct nothrow_t {}; | |
38 | } // namespace std | |
39 | ||
40 | #define OPERATOR_NEW_BODY(type) \ | |
41 | GET_STACK_TRACE_MALLOC;\ | |
42 | return asan_memalign(0, size, &stack, type); | |
43 | ||
44 | // On OS X it's not enough to just provide our own 'operator new' and | |
45 | // 'operator delete' implementations, because they're going to be in the | |
46 | // runtime dylib, and the main executable will depend on both the runtime | |
47 | // dylib and libstdc++, each of those'll have its implementation of new and | |
48 | // delete. | |
49 | // To make sure that C++ allocation/deallocation operators are overridden on | |
50 | // OS X we need to intercept them using their mangled names. | |
51 | #if !SANITIZER_MAC | |
52 | // FreeBSD prior v9.2 have wrong definition of 'size_t'. | |
53 | // http://svnweb.freebsd.org/base?view=revision&revision=232261 | |
54 | #if SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 | |
55 | #include <sys/param.h> | |
56 | #if __FreeBSD_version <= 902001 // v9.2 | |
57 | #define size_t unsigned | |
58 | #endif // __FreeBSD_version | |
59 | #endif // SANITIZER_FREEBSD && SANITIZER_WORDSIZE == 32 | |
60 | ||
92a42be0 | 61 | CXX_OPERATOR_ATTRIBUTE |
1a4d82fc | 62 | void *operator new(size_t size) { OPERATOR_NEW_BODY(FROM_NEW); } |
92a42be0 | 63 | CXX_OPERATOR_ATTRIBUTE |
1a4d82fc | 64 | void *operator new[](size_t size) { OPERATOR_NEW_BODY(FROM_NEW_BR); } |
92a42be0 | 65 | CXX_OPERATOR_ATTRIBUTE |
1a4d82fc JJ |
66 | void *operator new(size_t size, std::nothrow_t const&) |
67 | { OPERATOR_NEW_BODY(FROM_NEW); } | |
92a42be0 | 68 | CXX_OPERATOR_ATTRIBUTE |
1a4d82fc JJ |
69 | void *operator new[](size_t size, std::nothrow_t const&) |
70 | { OPERATOR_NEW_BODY(FROM_NEW_BR); } | |
71 | ||
72 | #else // SANITIZER_MAC | |
73 | INTERCEPTOR(void *, _Znwm, size_t size) { | |
74 | OPERATOR_NEW_BODY(FROM_NEW); | |
75 | } | |
76 | INTERCEPTOR(void *, _Znam, size_t size) { | |
77 | OPERATOR_NEW_BODY(FROM_NEW_BR); | |
78 | } | |
79 | INTERCEPTOR(void *, _ZnwmRKSt9nothrow_t, size_t size, std::nothrow_t const&) { | |
80 | OPERATOR_NEW_BODY(FROM_NEW); | |
81 | } | |
82 | INTERCEPTOR(void *, _ZnamRKSt9nothrow_t, size_t size, std::nothrow_t const&) { | |
83 | OPERATOR_NEW_BODY(FROM_NEW_BR); | |
84 | } | |
85 | #endif | |
86 | ||
87 | #define OPERATOR_DELETE_BODY(type) \ | |
88 | GET_STACK_TRACE_FREE;\ | |
89 | asan_free(ptr, &stack, type); | |
90 | ||
91 | #if !SANITIZER_MAC | |
92a42be0 SL |
92 | CXX_OPERATOR_ATTRIBUTE |
93 | void operator delete(void *ptr) NOEXCEPT { | |
1a4d82fc JJ |
94 | OPERATOR_DELETE_BODY(FROM_NEW); |
95 | } | |
92a42be0 SL |
96 | CXX_OPERATOR_ATTRIBUTE |
97 | void operator delete[](void *ptr) NOEXCEPT { | |
1a4d82fc JJ |
98 | OPERATOR_DELETE_BODY(FROM_NEW_BR); |
99 | } | |
92a42be0 | 100 | CXX_OPERATOR_ATTRIBUTE |
1a4d82fc JJ |
101 | void operator delete(void *ptr, std::nothrow_t const&) { |
102 | OPERATOR_DELETE_BODY(FROM_NEW); | |
103 | } | |
92a42be0 | 104 | CXX_OPERATOR_ATTRIBUTE |
1a4d82fc JJ |
105 | void operator delete[](void *ptr, std::nothrow_t const&) { |
106 | OPERATOR_DELETE_BODY(FROM_NEW_BR); | |
107 | } | |
92a42be0 SL |
108 | CXX_OPERATOR_ATTRIBUTE |
109 | void operator delete(void *ptr, size_t size) NOEXCEPT { | |
110 | GET_STACK_TRACE_FREE; | |
111 | asan_sized_free(ptr, size, &stack, FROM_NEW); | |
112 | } | |
113 | CXX_OPERATOR_ATTRIBUTE | |
114 | void operator delete[](void *ptr, size_t size) NOEXCEPT { | |
115 | GET_STACK_TRACE_FREE; | |
116 | asan_sized_free(ptr, size, &stack, FROM_NEW_BR); | |
117 | } | |
1a4d82fc JJ |
118 | |
119 | #else // SANITIZER_MAC | |
120 | INTERCEPTOR(void, _ZdlPv, void *ptr) { | |
121 | OPERATOR_DELETE_BODY(FROM_NEW); | |
122 | } | |
123 | INTERCEPTOR(void, _ZdaPv, void *ptr) { | |
124 | OPERATOR_DELETE_BODY(FROM_NEW_BR); | |
125 | } | |
126 | INTERCEPTOR(void, _ZdlPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { | |
127 | OPERATOR_DELETE_BODY(FROM_NEW); | |
128 | } | |
129 | INTERCEPTOR(void, _ZdaPvRKSt9nothrow_t, void *ptr, std::nothrow_t const&) { | |
130 | OPERATOR_DELETE_BODY(FROM_NEW_BR); | |
131 | } | |
132 | #endif |