1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_malloc_linux.cc ----------------------------------------------===//
21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//                     The LLVM Compiler Infrastructure
41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source
61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details.
71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Linux-specific malloc interception.
131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We simply define functions like malloc, free, realloc, etc.
141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// They will replace the corresponding libc functions automagically.
151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
1724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_common/sanitizer_platform.h"
1824e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_LINUX
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h"
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h"
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h"
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stack.h"
241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
2583cb7877f608eb9b3d65981095216842f686c527Evgeniy Stepanov#if SANITIZER_ANDROID
26c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, malloc, uptr size)
27c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void, free, void *ptr)
28c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, calloc, uptr nmemb, uptr size)
29c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, realloc, void *ptr, uptr size)
30c27279a4a08e0661f204c3e5dc65aafce79dec8aAlexey SamsonovDECLARE_REAL_AND_INTERCEPTOR(void*, memalign, uptr boundary, uptr size)
316dd1dde531b8fb6cf7a3e1dcda86170f6ac3a988Alexey Samsonov
321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystruct MallocDebug {
33e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany  void* (*malloc)(uptr bytes);
341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  void  (*free)(void* mem);
35e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany  void* (*calloc)(uptr n_elements, uptr elem_size);
36e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany  void* (*realloc)(void* oldMem, uptr bytes);
37e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany  void* (*memalign)(uptr alignment, uptr bytes);
381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany};
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
40adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonovconst MallocDebug asan_malloc_dispatch ALIGNED(32) = {
416dd1dde531b8fb6cf7a3e1dcda86170f6ac3a988Alexey Samsonov  WRAP(malloc), WRAP(free), WRAP(calloc), WRAP(realloc), WRAP(memalign)
421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany};
431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyextern "C" const MallocDebug* __libc_malloc_dispatch;
451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() {
481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  __libc_malloc_dispatch = &asan_malloc_dispatch;
491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#else  // ANDROID
531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid ReplaceSystemMalloc() {
561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif  // ANDROID
591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ---------------------- Replacement functions ---------------- {{{1
611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyusing namespace __asan;  // NOLINT
621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
63f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, free, void *ptr) {
64a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_FREE;
65fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  asan_free(ptr, &stack, FROM_MALLOC);
661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
68f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(void, cfree, void *ptr) {
69a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_FREE;
70fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  asan_free(ptr, &stack, FROM_MALLOC);
711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
73e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, malloc, uptr size) {
74a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return asan_malloc(size, &stack);
761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
78e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, calloc, uptr nmemb, uptr size) {
791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (!asan_inited) {
8009672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov    // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
81e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany    const uptr kCallocPoolSize = 1024;
823f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
83e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany    static uptr allocated;
84e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany    uptr size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    void *mem = (void*)&calloc_memory_for_dlsym[allocated];
861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    allocated += size_in_words;
871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK(allocated < kCallocPoolSize);
881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return mem;
891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
90a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return asan_calloc(nmemb, size, &stack);
921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
94e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, realloc, void *ptr, uptr size) {
95a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return asan_realloc(ptr, size, &stack);
971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
99e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
100a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
101fe6d91684bcda766593800f6307233f1a33d31f6Kostya Serebryany  return asan_memalign(boundary, size, &stack, FROM_MALLOC);
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
104e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, __libc_memalign, uptr align, uptr s)
105adf2b036127d7e887392d9be5b02069b777ee280Alexey Samsonov  ALIAS("memalign");
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
107e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
108a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
1094fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov  return asan_malloc_usable_size(ptr, &stack);
1104fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov}
1114fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonov
112e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// We avoid including malloc.h for portability reasons.
113e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// man mallinfo says the fields are "long", but the implementation uses int.
114e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// It doesn't matter much -- we just need to make sure that the libc's mallinfo
115e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany// is not called.
116e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryanystruct fake_mallinfo {
117e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany  int x[10];
118e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany};
119e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany
120e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
121e7539bf38e82db273708c5007bdb226c1a280b54Kostya Serebryany  struct fake_mallinfo res;
12209672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(memset)(&res, 0, sizeof(res));
1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return res;
1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
126f2598fc21bf651d23feab396a7581d48c01c3be5Alexey SamsonovINTERCEPTOR(int, mallopt, int cmd, int value) {
1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return -1;
1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
130e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
131a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
132739eb7984139d457216623347ae3b7a706c0aadfEvgeniy Stepanov  // Printf("posix_memalign: %zx %zu\n", alignment, size);
1331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return asan_posix_memalign(memptr, alignment, size, &stack);
1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
136e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, valloc, uptr size) {
137a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return asan_valloc(size, &stack);
1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
141e7539bf38e82db273708c5007bdb226c1a280b54Kostya SerebryanyINTERCEPTOR(void*, pvalloc, uptr size) {
142a30c8f9eac981dcf137e84226810b760e35c7be1Kostya Serebryany  GET_STACK_TRACE_MALLOC;
1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return asan_pvalloc(size, &stack);
1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
145d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany
14673bad81febb2a872627c03e579beea1da4b49294Kostya SerebryanyINTERCEPTOR(void, malloc_stats, void) {
147709a33e1cf20eb7f00653fe32dc07714b3f2c633Kostya Serebryany  __asan_print_accumulated_stats();
14873bad81febb2a872627c03e579beea1da4b49294Kostya Serebryany}
14973bad81febb2a872627c03e579beea1da4b49294Kostya Serebryany
150649a270f5341efe9c57f473dbb78706b0b2ed523Alexey Samsonov#endif  // SANITIZER_LINUX
151