memprof_malloc_linux.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //===-- memprof_malloc_linux.cpp -----------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of MemProfiler, a memory profiler.
  10. //
  11. // Linux-specific malloc interception.
  12. // We simply define functions like malloc, free, realloc, etc.
  13. // They will replace the corresponding libc functions automagically.
  14. //===----------------------------------------------------------------------===//
  15. #include "sanitizer_common/sanitizer_platform.h"
  16. #if !SANITIZER_LINUX
  17. #error Unsupported OS
  18. #endif
  19. #include "memprof_allocator.h"
  20. #include "memprof_interceptors.h"
  21. #include "memprof_internal.h"
  22. #include "memprof_stack.h"
  23. #include "sanitizer_common/sanitizer_allocator_checks.h"
  24. #include "sanitizer_common/sanitizer_allocator_dlsym.h"
  25. #include "sanitizer_common/sanitizer_errno.h"
  26. #include "sanitizer_common/sanitizer_tls_get_addr.h"
  27. // ---------------------- Replacement functions ---------------- {{{1
  28. using namespace __memprof;
  29. struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
  30. static bool UseImpl() { return memprof_init_is_running; }
  31. };
  32. INTERCEPTOR(void, free, void *ptr) {
  33. if (DlsymAlloc::PointerIsMine(ptr))
  34. return DlsymAlloc::Free(ptr);
  35. GET_STACK_TRACE_FREE;
  36. memprof_free(ptr, &stack, FROM_MALLOC);
  37. }
  38. #if SANITIZER_INTERCEPT_CFREE
  39. INTERCEPTOR(void, cfree, void *ptr) {
  40. if (DlsymAlloc::PointerIsMine(ptr))
  41. return DlsymAlloc::Free(ptr);
  42. GET_STACK_TRACE_FREE;
  43. memprof_free(ptr, &stack, FROM_MALLOC);
  44. }
  45. #endif // SANITIZER_INTERCEPT_CFREE
  46. INTERCEPTOR(void *, malloc, uptr size) {
  47. if (DlsymAlloc::Use())
  48. return DlsymAlloc::Allocate(size);
  49. ENSURE_MEMPROF_INITED();
  50. GET_STACK_TRACE_MALLOC;
  51. return memprof_malloc(size, &stack);
  52. }
  53. INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) {
  54. if (DlsymAlloc::Use())
  55. return DlsymAlloc::Callocate(nmemb, size);
  56. ENSURE_MEMPROF_INITED();
  57. GET_STACK_TRACE_MALLOC;
  58. return memprof_calloc(nmemb, size, &stack);
  59. }
  60. INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
  61. if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
  62. return DlsymAlloc::Realloc(ptr, size);
  63. ENSURE_MEMPROF_INITED();
  64. GET_STACK_TRACE_MALLOC;
  65. return memprof_realloc(ptr, size, &stack);
  66. }
  67. #if SANITIZER_INTERCEPT_REALLOCARRAY
  68. INTERCEPTOR(void *, reallocarray, void *ptr, uptr nmemb, uptr size) {
  69. ENSURE_MEMPROF_INITED();
  70. GET_STACK_TRACE_MALLOC;
  71. return memprof_reallocarray(ptr, nmemb, size, &stack);
  72. }
  73. #endif // SANITIZER_INTERCEPT_REALLOCARRAY
  74. #if SANITIZER_INTERCEPT_MEMALIGN
  75. INTERCEPTOR(void *, memalign, uptr boundary, uptr size) {
  76. GET_STACK_TRACE_MALLOC;
  77. return memprof_memalign(boundary, size, &stack, FROM_MALLOC);
  78. }
  79. INTERCEPTOR(void *, __libc_memalign, uptr boundary, uptr size) {
  80. GET_STACK_TRACE_MALLOC;
  81. void *res = memprof_memalign(boundary, size, &stack, FROM_MALLOC);
  82. DTLS_on_libc_memalign(res, size);
  83. return res;
  84. }
  85. #endif // SANITIZER_INTERCEPT_MEMALIGN
  86. #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
  87. INTERCEPTOR(void *, aligned_alloc, uptr boundary, uptr size) {
  88. GET_STACK_TRACE_MALLOC;
  89. return memprof_aligned_alloc(boundary, size, &stack);
  90. }
  91. #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC
  92. INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
  93. GET_CURRENT_PC_BP_SP;
  94. (void)sp;
  95. return memprof_malloc_usable_size(ptr, pc, bp);
  96. }
  97. #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
  98. // We avoid including malloc.h for portability reasons.
  99. // man mallinfo says the fields are "long", but the implementation uses int.
  100. // It doesn't matter much -- we just need to make sure that the libc's mallinfo
  101. // is not called.
  102. struct fake_mallinfo {
  103. int x[10];
  104. };
  105. INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
  106. struct fake_mallinfo res;
  107. REAL(memset)(&res, 0, sizeof(res));
  108. return res;
  109. }
  110. INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; }
  111. #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
  112. INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
  113. GET_STACK_TRACE_MALLOC;
  114. return memprof_posix_memalign(memptr, alignment, size, &stack);
  115. }
  116. INTERCEPTOR(void *, valloc, uptr size) {
  117. GET_STACK_TRACE_MALLOC;
  118. return memprof_valloc(size, &stack);
  119. }
  120. #if SANITIZER_INTERCEPT_PVALLOC
  121. INTERCEPTOR(void *, pvalloc, uptr size) {
  122. GET_STACK_TRACE_MALLOC;
  123. return memprof_pvalloc(size, &stack);
  124. }
  125. #endif // SANITIZER_INTERCEPT_PVALLOC
  126. INTERCEPTOR(void, malloc_stats, void) { __memprof_print_accumulated_stats(); }
  127. namespace __memprof {
  128. void ReplaceSystemMalloc() {}
  129. } // namespace __memprof