blob: 1fe848d6880c0250bdaa1b3cb5badf74f7becbb1 [file] [log] [blame]
Alexey Samsonov485d3dc2012-06-04 13:50:10 +00001//===-- asan_malloc_linux.cc ----------------------------------------------===//
Kostya Serebryany019b76f2011-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//===----------------------------------------------------------------------===//
Kostya Serebryany5dfa4da2011-12-01 21:40:52 +000016#ifdef __linux__
Kostya Serebryany019b76f2011-11-30 01:07:02 +000017
18#include "asan_allocator.h"
19#include "asan_interceptors.h"
20#include "asan_internal.h"
21#include "asan_stack.h"
22
Kostya Serebryany019b76f2011-11-30 01:07:02 +000023#ifdef ANDROID
Alexey Samsonov941a6ec2012-08-06 15:13:22 +000024DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size);
25DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr);
26DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size);
27DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size);
28DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size);
29
Kostya Serebryany019b76f2011-11-30 01:07:02 +000030struct MallocDebug {
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000031 void* (*malloc)(uptr bytes);
Kostya Serebryany019b76f2011-11-30 01:07:02 +000032 void (*free)(void* mem);
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000033 void* (*calloc)(uptr n_elements, uptr elem_size);
34 void* (*realloc)(void* oldMem, uptr bytes);
35 void* (*memalign)(uptr alignment, uptr bytes);
Kostya Serebryany019b76f2011-11-30 01:07:02 +000036};
37
Alexey Samsonov23e3b902012-02-03 08:37:19 +000038const MallocDebug asan_malloc_dispatch ALIGNED(32) = {
Alexey Samsonov941a6ec2012-08-06 15:13:22 +000039 WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign)
Kostya Serebryany019b76f2011-11-30 01:07:02 +000040};
41
42extern "C" const MallocDebug* __libc_malloc_dispatch;
43
44namespace __asan {
45void ReplaceSystemMalloc() {
46 __libc_malloc_dispatch = &asan_malloc_dispatch;
47}
48} // namespace __asan
49
50#else // ANDROID
51
52namespace __asan {
53void ReplaceSystemMalloc() {
54}
55} // namespace __asan
56#endif // ANDROID
57
58// ---------------------- Replacement functions ---------------- {{{1
59using namespace __asan; // NOLINT
60
Alexey Samsonov15965f92012-02-02 10:39:40 +000061INTERCEPTOR(void, free, void *ptr) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +000062 GET_STACK_TRACE_HERE_FOR_FREE(ptr);
63 asan_free(ptr, &stack);
64}
65
Alexey Samsonov15965f92012-02-02 10:39:40 +000066INTERCEPTOR(void, cfree, void *ptr) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +000067 GET_STACK_TRACE_HERE_FOR_FREE(ptr);
68 asan_free(ptr, &stack);
69}
70
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000071INTERCEPTOR(void*, malloc, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +000072 GET_STACK_TRACE_HERE_FOR_MALLOC;
73 return asan_malloc(size, &stack);
74}
75
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000076INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +000077 if (!asan_inited) {
Alexey Samsonove7254782012-02-08 13:45:31 +000078 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000079 const uptr kCallocPoolSize = 1024;
Kostya Serebryany8d032042012-05-31 14:35:53 +000080 static uptr calloc_memory_for_dlsym[kCallocPoolSize];
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000081 static uptr allocated;
82 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
Kostya Serebryany019b76f2011-11-30 01:07:02 +000083 void *mem = (void*)&calloc_memory_for_dlsym[allocated];
84 allocated += size_in_words;
85 CHECK(allocated < kCallocPoolSize);
86 return mem;
87 }
88 GET_STACK_TRACE_HERE_FOR_MALLOC;
89 return asan_calloc(nmemb, size, &stack);
90}
91
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000092INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +000093 GET_STACK_TRACE_HERE_FOR_MALLOC;
94 return asan_realloc(ptr, size, &stack);
95}
96
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000097INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +000098 GET_STACK_TRACE_HERE_FOR_MALLOC;
99 return asan_memalign(boundary, size, &stack);
100}
101
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000102INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
Alexey Samsonov23e3b902012-02-03 08:37:19 +0000103 ALIAS("memalign");
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000104
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000105INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
Alexey Samsonov209c5142012-01-17 06:39:10 +0000106 GET_STACK_TRACE_HERE_FOR_MALLOC;
107 return asan_malloc_usable_size(ptr, &stack);
108}
109
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000110// We avoid including malloc.h for portability reasons.
111// man mallinfo says the fields are "long", but the implementation uses int.
112// It doesn't matter much -- we just need to make sure that the libc's mallinfo
113// is not called.
114struct fake_mallinfo {
115 int x[10];
116};
117
118INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
119 struct fake_mallinfo res;
Alexey Samsonove7254782012-02-08 13:45:31 +0000120 REAL(memset)(&res, 0, sizeof(res));
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000121 return res;
122}
123
Alexey Samsonov15965f92012-02-02 10:39:40 +0000124INTERCEPTOR(int, mallopt, int cmd, int value) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000125 return -1;
126}
127
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000128INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000129 GET_STACK_TRACE_HERE_FOR_MALLOC;
Evgeniy Stepanov823085a2012-03-21 11:32:46 +0000130 // Printf("posix_memalign: %zx %zu\n", alignment, size);
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000131 return asan_posix_memalign(memptr, alignment, size, &stack);
132}
133
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000134INTERCEPTOR(void*, valloc, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000135 GET_STACK_TRACE_HERE_FOR_MALLOC;
136 return asan_valloc(size, &stack);
137}
138
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000139INTERCEPTOR(void*, pvalloc, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000140 GET_STACK_TRACE_HERE_FOR_MALLOC;
141 return asan_pvalloc(size, &stack);
142}
Kostya Serebryany5dfa4da2011-12-01 21:40:52 +0000143
144#endif // __linux__