asan_malloc_linux.cc revision 73bad81febb2a872627c03e579beea1da4b49294
1//===-- asan_malloc_linux.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// Linux-specific malloc interception.
13// We simply define functions like malloc, free, realloc, etc.
14// They will replace the corresponding libc functions automagically.
15//===----------------------------------------------------------------------===//
16#ifdef __linux__
17
18#include "asan_allocator.h"
19#include "asan_interceptors.h"
20#include "asan_internal.h"
21#include "asan_stack.h"
22#include "asan_thread_registry.h"
23
24#if ASAN_ANDROID
25DECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size)
26DECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
27DECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size)
28DECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size)
29DECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size)
30
31struct MallocDebug {
32  void* (*malloc)(uptr bytes);
33  void  (*free)(void* mem);
34  void* (*calloc)(uptr n_elements, uptr elem_size);
35  void* (*realloc)(void* oldMem, uptr bytes);
36  void* (*memalign)(uptr alignment, uptr bytes);
37};
38
39const MallocDebug asan_malloc_dispatch ALIGNED(32) = {
40  WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign)
41};
42
43extern "C" const MallocDebug* __libc_malloc_dispatch;
44
45namespace __asan {
46void ReplaceSystemMalloc() {
47  __libc_malloc_dispatch = &asan_malloc_dispatch;
48}
49}  // namespace __asan
50
51#else  // ANDROID
52
53namespace __asan {
54void ReplaceSystemMalloc() {
55}
56}  // namespace __asan
57#endif  // ANDROID
58
59// ---------------------- Replacement functions ---------------- {{{1
60using namespace __asan;  // NOLINT
61
62INTERCEPTOR(void, free, void *ptr) {
63  GET_STACK_TRACE_FREE;
64  asan_free(ptr, &stack);
65}
66
67INTERCEPTOR(void, cfree, void *ptr) {
68  GET_STACK_TRACE_FREE;
69  asan_free(ptr, &stack);
70}
71
72INTERCEPTOR(void*, malloc, uptr size) {
73  GET_STACK_TRACE_MALLOC;
74  return asan_malloc(size, &stack);
75}
76
77INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
78  if (!asan_inited) {
79    // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
80    const uptr kCallocPoolSize = 1024;
81    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
82    static uptr allocated;
83    uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
84    void *mem = (void*)&calloc_memory_for_dlsym[allocated];
85    allocated += size_in_words;
86    CHECK(allocated < kCallocPoolSize);
87    return mem;
88  }
89  GET_STACK_TRACE_MALLOC;
90  return asan_calloc(nmemb, size, &stack);
91}
92
93INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
94  GET_STACK_TRACE_MALLOC;
95  return asan_realloc(ptr, size, &stack);
96}
97
98INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
99  GET_STACK_TRACE_MALLOC;
100  return asan_memalign(boundary, size, &stack);
101}
102
103INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
104  ALIAS("memalign");
105
106INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
107  GET_STACK_TRACE_MALLOC;
108  return asan_malloc_usable_size(ptr, &stack);
109}
110
111// We avoid including malloc.h for portability reasons.
112// man mallinfo says the fields are "long", but the implementation uses int.
113// It doesn't matter much -- we just need to make sure that the libc's mallinfo
114// is not called.
115struct fake_mallinfo {
116  int x[10];
117};
118
119INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
120  struct fake_mallinfo res;
121  REAL(memset)(&res, 0, sizeof(res));
122  return res;
123}
124
125INTERCEPTOR(int, mallopt, int cmd, int value) {
126  return -1;
127}
128
129INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
130  GET_STACK_TRACE_MALLOC;
131  // Printf("posix_memalign: %zx %zu\n", alignment, size);
132  return asan_posix_memalign(memptr, alignment, size, &stack);
133}
134
135INTERCEPTOR(void*, valloc, uptr size) {
136  GET_STACK_TRACE_MALLOC;
137  return asan_valloc(size, &stack);
138}
139
140INTERCEPTOR(void*, pvalloc, uptr size) {
141  GET_STACK_TRACE_MALLOC;
142  return asan_pvalloc(size, &stack);
143}
144
145INTERCEPTOR(void, malloc_stats, void) {
146  Printf("AddressSanitizer malloc_stats()\n");
147  Printf("  total mmapped: %zdM\n",
148         asanThreadRegistry().GetHeapSize() >> 20);
149}
150
151#endif  // __linux__
152