blob: b95cfe3149b74e8b24856952c9888ded18185297 [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"
Kostya Serebryany9da3dd02012-12-20 11:54:21 +000022#include "asan_thread_registry.h"
Kostya Serebryany390cf942012-12-26 12:20:35 +000023#include "sanitizer/asan_interface.h"
Kostya Serebryany019b76f2011-11-30 01:07:02 +000024
Evgeniy Stepanovbe013982012-08-27 11:15:55 +000025#if ASAN_ANDROID
Alexey Samsonova81d2682012-09-12 09:42:23 +000026DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size)
27DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
28DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size)
29DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size)
30DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size)
Alexey Samsonov941a6ec2012-08-06 15:13:22 +000031
Kostya Serebryany019b76f2011-11-30 01:07:02 +000032struct MallocDebug {
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000033 void* (*malloc)(uptr bytes);
Kostya Serebryany019b76f2011-11-30 01:07:02 +000034 void (*free)(void* mem);
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000035 void* (*calloc)(uptr n_elements, uptr elem_size);
36 void* (*realloc)(void* oldMem, uptr bytes);
37 void* (*memalign)(uptr alignment, uptr bytes);
Kostya Serebryany019b76f2011-11-30 01:07:02 +000038};
39
Alexey Samsonov23e3b902012-02-03 08:37:19 +000040const MallocDebug asan_malloc_dispatch ALIGNED(32) = {
Alexey Samsonov941a6ec2012-08-06 15:13:22 +000041 WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign)
Kostya Serebryany019b76f2011-11-30 01:07:02 +000042};
43
44extern "C" const MallocDebug* __libc_malloc_dispatch;
45
46namespace __asan {
47void ReplaceSystemMalloc() {
48 __libc_malloc_dispatch = &asan_malloc_dispatch;
49}
50} // namespace __asan
51
52#else // ANDROID
53
54namespace __asan {
55void ReplaceSystemMalloc() {
56}
57} // namespace __asan
58#endif // ANDROID
59
60// ---------------------- Replacement functions ---------------- {{{1
61using namespace __asan; // NOLINT
62
Alexey Samsonov15965f92012-02-02 10:39:40 +000063INTERCEPTOR(void, free, void *ptr) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +000064 GET_STACK_TRACE_FREE;
Kostya Serebryany3674c6b2012-12-21 08:53:59 +000065 asan_free(ptr, &stack, FROM_MALLOC);
Kostya Serebryany019b76f2011-11-30 01:07:02 +000066}
67
Alexey Samsonov15965f92012-02-02 10:39:40 +000068INTERCEPTOR(void, cfree, void *ptr) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +000069 GET_STACK_TRACE_FREE;
Kostya Serebryany3674c6b2012-12-21 08:53:59 +000070 asan_free(ptr, &stack, FROM_MALLOC);
Kostya Serebryany019b76f2011-11-30 01:07:02 +000071}
72
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000073INTERCEPTOR(void*, malloc, uptr size) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +000074 GET_STACK_TRACE_MALLOC;
Kostya Serebryany019b76f2011-11-30 01:07:02 +000075 return asan_malloc(size, &stack);
76}
77
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000078INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +000079 if (!asan_inited) {
Alexey Samsonove7254782012-02-08 13:45:31 +000080 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000081 const uptr kCallocPoolSize = 1024;
Kostya Serebryany8d032042012-05-31 14:35:53 +000082 static uptr calloc_memory_for_dlsym[kCallocPoolSize];
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000083 static uptr allocated;
84 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
Kostya Serebryany019b76f2011-11-30 01:07:02 +000085 void *mem = (void*)&calloc_memory_for_dlsym[allocated];
86 allocated += size_in_words;
87 CHECK(allocated < kCallocPoolSize);
88 return mem;
89 }
Kostya Serebryanybaf583c2012-12-13 09:34:23 +000090 GET_STACK_TRACE_MALLOC;
Kostya Serebryany019b76f2011-11-30 01:07:02 +000091 return asan_calloc(nmemb, size, &stack);
92}
93
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000094INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +000095 GET_STACK_TRACE_MALLOC;
Kostya Serebryany019b76f2011-11-30 01:07:02 +000096 return asan_realloc(ptr, size, &stack);
97}
98
Kostya Serebryany0e0832b2012-06-25 09:58:29 +000099INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +0000100 GET_STACK_TRACE_MALLOC;
Kostya Serebryany3674c6b2012-12-21 08:53:59 +0000101 return asan_memalign(boundary, size, &stack, FROM_MALLOC);
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000102}
103
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000104INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
Alexey Samsonov23e3b902012-02-03 08:37:19 +0000105 ALIAS("memalign");
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000106
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000107INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +0000108 GET_STACK_TRACE_MALLOC;
Alexey Samsonov209c5142012-01-17 06:39:10 +0000109 return asan_malloc_usable_size(ptr, &stack);
110}
111
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000112// We avoid including malloc.h for portability reasons.
113// man mallinfo says the fields are "long", but the implementation uses int.
114// It doesn't matter much -- we just need to make sure that the libc's mallinfo
115// is not called.
116struct fake_mallinfo {
117 int x[10];
118};
119
120INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
121 struct fake_mallinfo res;
Alexey Samsonove7254782012-02-08 13:45:31 +0000122 REAL(memset)(&res, 0, sizeof(res));
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000123 return res;
124}
125
Alexey Samsonov15965f92012-02-02 10:39:40 +0000126INTERCEPTOR(int, mallopt, int cmd, int value) {
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000127 return -1;
128}
129
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000130INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +0000131 GET_STACK_TRACE_MALLOC;
Evgeniy Stepanov823085a2012-03-21 11:32:46 +0000132 // Printf("posix_memalign: %zx %zu\n", alignment, size);
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000133 return asan_posix_memalign(memptr, alignment, size, &stack);
134}
135
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000136INTERCEPTOR(void*, valloc, uptr size) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +0000137 GET_STACK_TRACE_MALLOC;
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000138 return asan_valloc(size, &stack);
139}
140
Kostya Serebryany0e0832b2012-06-25 09:58:29 +0000141INTERCEPTOR(void*, pvalloc, uptr size) {
Kostya Serebryanybaf583c2012-12-13 09:34:23 +0000142 GET_STACK_TRACE_MALLOC;
Kostya Serebryany019b76f2011-11-30 01:07:02 +0000143 return asan_pvalloc(size, &stack);
144}
Kostya Serebryany5dfa4da2011-12-01 21:40:52 +0000145
Kostya Serebryany9da3dd02012-12-20 11:54:21 +0000146INTERCEPTOR(void, malloc_stats, void) {
Kostya Serebryany390cf942012-12-26 12:20:35 +0000147 __asan_print_accumulated_stats();
Kostya Serebryany9da3dd02012-12-20 11:54:21 +0000148}
149
Kostya Serebryany5dfa4da2011-12-01 21:40:52 +0000150#endif // __linux__