blob: 24b7f6977927626764a91ae355596a5d59544b93 [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"
18#if SANITIZER_LINUX
Kostya Serebryany1e172b42011-11-30 01:07:02 +000019
20#include "asan_allocator.h"
21#include "asan_interceptors.h"
22#include "asan_internal.h"
23#include "asan_stack.h"
24
Evgeniy Stepanov83cb7872013-03-19 13:54:41 +000025#if SANITIZER_ANDROID
Alexey Samsonovc27279a2012-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 Samsonov6dd1dde2012-08-06 15:13:22 +000031
Kostya Serebryany1e172b42011-11-30 01:07:02 +000032struct MallocDebug {
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000033 void* (*malloc)(uptr bytes);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000034 void (*free)(void* mem);
Kostya Serebryanye7539bf2012-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 Serebryany1e172b42011-11-30 01:07:02 +000038};
39
Alexey Samsonovadf2b032012-02-03 08:37:19 +000040const MallocDebug asan_malloc_dispatch ALIGNED(32) = {
Alexey Samsonov6dd1dde2012-08-06 15:13:22 +000041 WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign)
Kostya Serebryany1e172b42011-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 Samsonovf2598fc2012-02-02 10:39:40 +000063INTERCEPTOR(void, free, void *ptr) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000064 GET_STACK_TRACE_FREE;
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +000065 asan_free(ptr, &stack, FROM_MALLOC);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000066}
67
Alexey Samsonovf2598fc2012-02-02 10:39:40 +000068INTERCEPTOR(void, cfree, void *ptr) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000069 GET_STACK_TRACE_FREE;
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +000070 asan_free(ptr, &stack, FROM_MALLOC);
Kostya Serebryany1e172b42011-11-30 01:07:02 +000071}
72
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000073INTERCEPTOR(void*, malloc, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000074 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000075 return asan_malloc(size, &stack);
76}
77
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000078INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +000079 if (!asan_inited) {
Alexey Samsonov09672ca2012-02-08 13:45:31 +000080 // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000081 const uptr kCallocPoolSize = 1024;
Kostya Serebryany3f4c3872012-05-31 14:35:53 +000082 static uptr calloc_memory_for_dlsym[kCallocPoolSize];
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000083 static uptr allocated;
84 uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
Kostya Serebryany1e172b42011-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 Serebryanya30c8f92012-12-13 09:34:23 +000090 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000091 return asan_calloc(nmemb, size, &stack);
92}
93
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000094INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +000095 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +000096 return asan_realloc(ptr, size, &stack);
97}
98
Kostya Serebryanye7539bf2012-06-25 09:58:29 +000099INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000100 GET_STACK_TRACE_MALLOC;
Kostya Serebryanyfe6d9162012-12-21 08:53:59 +0000101 return asan_memalign(boundary, size, &stack, FROM_MALLOC);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000102}
103
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000104INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
Alexey Samsonovadf2b032012-02-03 08:37:19 +0000105 ALIAS("memalign");
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000106
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000107INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
Alexey Samsonov1b17f5b2013-11-13 14:46:58 +0000108 GET_CURRENT_PC_BP_SP;
109 (void)sp;
110 return asan_malloc_usable_size(ptr, pc, bp);
Alexey Samsonov4fd95f12012-01-17 06:39:10 +0000111}
112
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000113// We avoid including malloc.h for portability reasons.
114// man mallinfo says the fields are "long", but the implementation uses int.
115// It doesn't matter much -- we just need to make sure that the libc's mallinfo
116// is not called.
117struct fake_mallinfo {
118 int x[10];
119};
120
121INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
122 struct fake_mallinfo res;
Alexey Samsonov09672ca2012-02-08 13:45:31 +0000123 REAL(memset)(&res, 0, sizeof(res));
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000124 return res;
125}
126
Alexey Samsonovf2598fc2012-02-02 10:39:40 +0000127INTERCEPTOR(int, mallopt, int cmd, int value) {
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000128 return -1;
129}
130
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000131INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000132 GET_STACK_TRACE_MALLOC;
Evgeniy Stepanov739eb792012-03-21 11:32:46 +0000133 // Printf("posix_memalign: %zx %zu\n", alignment, size);
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000134 return asan_posix_memalign(memptr, alignment, size, &stack);
135}
136
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000137INTERCEPTOR(void*, valloc, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000138 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000139 return asan_valloc(size, &stack);
140}
141
Kostya Serebryanye7539bf2012-06-25 09:58:29 +0000142INTERCEPTOR(void*, pvalloc, uptr size) {
Kostya Serebryanya30c8f92012-12-13 09:34:23 +0000143 GET_STACK_TRACE_MALLOC;
Kostya Serebryany1e172b42011-11-30 01:07:02 +0000144 return asan_pvalloc(size, &stack);
145}
Kostya Serebryanyd6567c52011-12-01 21:40:52 +0000146
Kostya Serebryany73bad812012-12-20 11:54:21 +0000147INTERCEPTOR(void, malloc_stats, void) {
Kostya Serebryany709a33e2012-12-26 12:20:35 +0000148 __asan_print_accumulated_stats();
Kostya Serebryany73bad812012-12-20 11:54:21 +0000149}
150
Alexey Samsonov649a2702013-04-03 07:29:53 +0000151#endif // SANITIZER_LINUX