blob: 46a6a9db4a8122f48c9040812dc5efeed685b1f0 [file] [log] [blame]
Alexey Samsonove5f58952012-06-04 13:50:10 +00001//===-- asan_malloc_linux.cc ----------------------------------------------===//
Kostya Serebryany1e172b42011-11-30 01:07:02 +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// Linux-specific malloc interception.
13// We simply define functions like malloc, free, realloc, etc.
14// They will replace the corresponding libc functions automagically.
15//===----------------------------------------------------------------------===//
Evgeniy Stepanov24e13722013-03-19 14:33:38 +000016
17#include "sanitizer_common/sanitizer_platform.h"
Stephen Hines2d1fdb22014-05-28 23:58:16 -070018#if SANITIZER_FREEBSD || SANITIZER_LINUX
Kostya Serebryany1e172b42011-11-30 01:07:02 +000019
Stephen Hines2d1fdb22014-05-28 23:58:16 -070020#include "sanitizer_common/sanitizer_tls_get_addr.h"
Kostya Serebryany1e172b42011-11-30 01:07:02 +000021#include "asan_allocator.h"
22#include "asan_interceptors.h"
23#include "asan_internal.h"
24#include "asan_stack.h"
25
Kostya Serebryany1e172b42011-11-30 01:07:02 +000026// ---------------------- Replacement functions ---------------- {{{1
27using namespace __asan; // NOLINT
28
Alexey Samsonovf2598fc2012-02-02 10:39:40 +000029INTERCEPTOR(void, free, void *ptr) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000030 GET_STACK_TRACE_FREE;
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +000031 asan_free(ptr, &stack, FROM_MALLOC);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000032}
33
Alexey Samsonovf2598fc2012-02-02 10:39:40 +000034INTERCEPTOR(void, cfree, void *ptr) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000035 GET_STACK_TRACE_FREE;
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +000036 asan_free(ptr, &stack, FROM_MALLOC);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000037}
38
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000039INTERCEPTOR(void*, malloc, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000040 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000041 return asan_malloc(size, &stack);
42}
43
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000044INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
Stephen Hines2d1fdb22014-05-28 23:58:16 -070045 if (UNLIKELY(!asan_inited)) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +000046 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000047 const uptr kCallocPoolSize = 1024;
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000048 static uptr calloc_memory_for_dlsym[kCallocPoolSize];
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000049 static uptr allocated;
50 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000051 void *mem = (void*)&calloc_memory_for_dlsym[allocated];
52 allocated += size_in_words;
53 CHECK(allocated < kCallocPoolSize);
54 return mem;
55 }
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000056 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000057 return asan_calloc(nmemb, size, &stack);
58}
59
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000060INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000061 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000062 return asan_realloc(ptr, size, &stack);
63}
64
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000065INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000066 GET_STACK_TRACE_MALLOC;
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +000067 return asan_memalign(boundary, size, &stack, FROM_MALLOC);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000068}
69
Stephen Hines6a211c52014-07-21 00:49:56 -070070INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
71 GET_STACK_TRACE_MALLOC;
72 return asan_memalign(boundary, size, &stack, FROM_MALLOC);
73}
74
Stephen Hines2d1fdb22014-05-28 23:58:16 -070075INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
76 GET_STACK_TRACE_MALLOC;
77 void *res = asan_memalign(boundary, size, &stack, FROM_MALLOC);
78 DTLS_on_libc_memalign(res, size * boundary);
79 return res;
80}
Kostya Serebryany1e172b42011-11-30 01:07:02 +000081
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000082INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
Alexey Samsonov1b17f5b2013-11-13 14:46:58 +000083 GET_CURRENT_PC_BP_SP;
84 (void)sp;
85 return asan_malloc_usable_size(ptr, pc, bp);
Alexey Samsonov4fd95f12012-01-17 06:39:10 +000086}
87
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000088// We avoid including malloc.h for portability reasons.
89// man mallinfo says the fields are "long", but the implementation uses int.
90// It doesn't matter much -- we just need to make sure that the libc's mallinfo
91// is not called.
92struct fake_mallinfo {
93 int x[10];
94};
95
96INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
97 struct fake_mallinfo res;
Alexey Samsonov09672ca2012-02-08 13:45:31 +000098 REAL(memset)(&res, 0, sizeof(res));
Kostya Serebryany1e172b42011-11-30 01:07:02 +000099 return res;
100}
101
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000102INTERCEPTOR(int, mallopt, int cmd, int value) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000103 return -1;
104}
105
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000106INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000107 GET_STACK_TRACE_MALLOC;
Evgeniy Stepanov739eb792012-03-21 11:32:46 +0000108 // Printf("posix_memalign: %zx %zu\n", alignment, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000109 return asan_posix_memalign(memptr, alignment, size, &stack);
110}
111
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000112INTERCEPTOR(void*, valloc, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000113 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000114 return asan_valloc(size, &stack);
115}
116
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000117INTERCEPTOR(void*, pvalloc, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000118 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000119 return asan_pvalloc(size, &stack);
120}
Kostya Serebryanyd6567c52011-12-01 21:40:52 +0000121
Kostya Serebryany73bad812012-12-20 11:54:21 +0000122INTERCEPTOR(void, malloc_stats, void) {
Kostya Serebryany709a33e2012-12-26 12:20:35 +0000123 __asan_print_accumulated_stats();
Kostya Serebryany73bad812012-12-20 11:54:21 +0000124}
125
Stephen Hines6d186232014-11-26 17:56:19 -0800126#if SANITIZER_ANDROID
127// Format of __libc_malloc_dispatch has changed in Android L.
128// While we are moving towards a solution that does not depend on bionic
129// internals, here is something to support both K* and L releases.
130struct MallocDebugK {
131 void *(*malloc)(uptr bytes);
132 void (*free)(void *mem);
133 void *(*calloc)(uptr n_elements, uptr elem_size);
134 void *(*realloc)(void *oldMem, uptr bytes);
135 void *(*memalign)(uptr alignment, uptr bytes);
136 uptr (*malloc_usable_size)(void *mem);
137};
138
139struct MallocDebugL {
140 void *(*calloc)(uptr n_elements, uptr elem_size);
141 void (*free)(void *mem);
142 fake_mallinfo (*mallinfo)(void);
143 void *(*malloc)(uptr bytes);
144 uptr (*malloc_usable_size)(void *mem);
145 void *(*memalign)(uptr alignment, uptr bytes);
146 int (*posix_memalign)(void **memptr, uptr alignment, uptr size);
147 void* (*pvalloc)(uptr size);
148 void *(*realloc)(void *oldMem, uptr bytes);
149 void* (*valloc)(uptr size);
150};
151
152ALIGNED(32) const MallocDebugK asan_malloc_dispatch_k = {
153 WRAP(malloc), WRAP(free), WRAP(calloc),
154 WRAP(realloc), WRAP(memalign), WRAP(malloc_usable_size)};
155
156ALIGNED(32) const MallocDebugL asan_malloc_dispatch_l = {
157 WRAP(calloc), WRAP(free), WRAP(mallinfo),
158 WRAP(malloc), WRAP(malloc_usable_size), WRAP(memalign),
159 WRAP(posix_memalign), WRAP(pvalloc), WRAP(realloc),
160 WRAP(valloc)};
161
162namespace __asan {
163void ReplaceSystemMalloc() {
164 void **__libc_malloc_dispatch_p =
165 (void **)AsanDlSymNext("__libc_malloc_dispatch");
166 if (__libc_malloc_dispatch_p) {
167 // Decide on K vs L dispatch format by the presence of
168 // __libc_malloc_default_dispatch export in libc.
169 void *default_dispatch_p = AsanDlSymNext("__libc_malloc_default_dispatch");
170 if (default_dispatch_p)
171 *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_k;
172 else
173 *__libc_malloc_dispatch_p = (void *)&asan_malloc_dispatch_l;
174 }
175}
176} // namespace __asan
177
178#else // SANITIZER_ANDROID
179
180namespace __asan {
181void ReplaceSystemMalloc() {
182}
183} // namespace __asan
184#endif // SANITIZER_ANDROID
185
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700186#endif // SANITIZER_FREEBSD || SANITIZER_LINUX