asan_malloc_linux.cc revision a30c8f9eac981dcf137e84226810b760e35c7be1
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
23#if ASAN_ANDROID
24DECLARE_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
30struct MallocDebug {
31  void* (*malloc)(uptr bytes);
32  void  (*free)(void* mem);
33  void* (*calloc)(uptr n_elements, uptr elem_size);
34  void* (*realloc)(void* oldMem, uptr bytes);
35  void* (*memalign)(uptr alignment, uptr bytes);
36};
37
38const MallocDebug asan_malloc_dispatch ALIGNED(32) = {
39  WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign)
40};
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
61INTERCEPTOR(void, free, void *ptr) {
62  GET_STACK_TRACE_FREE;
63  asan_free(ptr, &stack);
64}
65
66INTERCEPTOR(void, cfree, void *ptr) {
67  GET_STACK_TRACE_FREE;
68  asan_free(ptr, &stack);
69}
70
71INTERCEPTOR(void*, malloc, uptr size) {
72  GET_STACK_TRACE_MALLOC;
73  return asan_malloc(size, &stack);
74}
75
76INTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
77  if (!asan_inited) {
78    // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
79    const uptr kCallocPoolSize = 1024;
80    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
81    static uptr allocated;
82    uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
83    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_MALLOC;
89  return asan_calloc(nmemb, size, &stack);
90}
91
92INTERCEPTOR(void*, realloc, void *ptr, uptr size) {
93  GET_STACK_TRACE_MALLOC;
94  return asan_realloc(ptr, size, &stack);
95}
96
97INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
98  GET_STACK_TRACE_MALLOC;
99  return asan_memalign(boundary, size, &stack);
100}
101
102INTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
103  ALIAS("memalign");
104
105INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
106  GET_STACK_TRACE_MALLOC;
107  return asan_malloc_usable_size(ptr, &stack);
108}
109
110// 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;
120  REAL(memset)(&res, 0, sizeof(res));
121  return res;
122}
123
124INTERCEPTOR(int, mallopt, int cmd, int value) {
125  return -1;
126}
127
128INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
129  GET_STACK_TRACE_MALLOC;
130  // Printf("posix_memalign: %zx %zu\n", alignment, size);
131  return asan_posix_memalign(memptr, alignment, size, &stack);
132}
133
134INTERCEPTOR(void*, valloc, uptr size) {
135  GET_STACK_TRACE_MALLOC;
136  return asan_valloc(size, &stack);
137}
138
139INTERCEPTOR(void*, pvalloc, uptr size) {
140  GET_STACK_TRACE_MALLOC;
141  return asan_pvalloc(size, &stack);
142}
143
144#endif  // __linux__
145