xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/memprof/memprof_interceptors.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1e8d8bef9SDimitry Andric //===-- memprof_interceptors.cpp -----------------------------------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric //
9e8d8bef9SDimitry Andric // This file is a part of MemProfiler, a memory profiler.
10e8d8bef9SDimitry Andric //
11e8d8bef9SDimitry Andric // Intercept various libc functions.
12e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
13e8d8bef9SDimitry Andric 
14e8d8bef9SDimitry Andric #include "memprof_interceptors.h"
15e8d8bef9SDimitry Andric #include "memprof_allocator.h"
16e8d8bef9SDimitry Andric #include "memprof_internal.h"
17e8d8bef9SDimitry Andric #include "memprof_mapping.h"
18e8d8bef9SDimitry Andric #include "memprof_stack.h"
19e8d8bef9SDimitry Andric #include "memprof_stats.h"
20e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_libc.h"
21e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_posix.h"
22e8d8bef9SDimitry Andric 
23e8d8bef9SDimitry Andric namespace __memprof {
24e8d8bef9SDimitry Andric 
25e8d8bef9SDimitry Andric #define MEMPROF_READ_STRING(s, n) MEMPROF_READ_RANGE((s), (n))
26e8d8bef9SDimitry Andric 
27e8d8bef9SDimitry Andric static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) {
28e8d8bef9SDimitry Andric #if SANITIZER_INTERCEPT_STRNLEN
29e8d8bef9SDimitry Andric   if (REAL(strnlen)) {
30e8d8bef9SDimitry Andric     return REAL(strnlen)(s, maxlen);
31e8d8bef9SDimitry Andric   }
32e8d8bef9SDimitry Andric #endif
33e8d8bef9SDimitry Andric   return internal_strnlen(s, maxlen);
34e8d8bef9SDimitry Andric }
35e8d8bef9SDimitry Andric 
36e8d8bef9SDimitry Andric void SetThreadName(const char *name) {
37e8d8bef9SDimitry Andric   MemprofThread *t = GetCurrentThread();
38e8d8bef9SDimitry Andric   if (t)
39e8d8bef9SDimitry Andric     memprofThreadRegistry().SetThreadName(t->tid(), name);
40e8d8bef9SDimitry Andric }
41e8d8bef9SDimitry Andric 
42e8d8bef9SDimitry Andric int OnExit() {
43e8d8bef9SDimitry Andric   // FIXME: ask frontend whether we need to return failure.
44e8d8bef9SDimitry Andric   return 0;
45e8d8bef9SDimitry Andric }
46e8d8bef9SDimitry Andric 
47e8d8bef9SDimitry Andric } // namespace __memprof
48e8d8bef9SDimitry Andric 
49e8d8bef9SDimitry Andric // ---------------------- Wrappers ---------------- {{{1
50e8d8bef9SDimitry Andric using namespace __memprof;
51e8d8bef9SDimitry Andric 
52e8d8bef9SDimitry Andric DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr)
53e8d8bef9SDimitry Andric DECLARE_REAL_AND_INTERCEPTOR(void, free, void *)
54e8d8bef9SDimitry Andric 
55e8d8bef9SDimitry Andric #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                               \
56e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC_VER(name, ver)
57fe6060f1SDimitry Andric #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver)          \
58fe6060f1SDimitry Andric   MEMPROF_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
59e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                         \
60e8d8bef9SDimitry Andric   MEMPROF_WRITE_RANGE(ptr, size)
61e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)                          \
62e8d8bef9SDimitry Andric   MEMPROF_READ_RANGE(ptr, size)
63e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
64e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, func);                                        \
65e8d8bef9SDimitry Andric   do {                                                                         \
66e8d8bef9SDimitry Andric     if (memprof_init_is_running)                                               \
67e8d8bef9SDimitry Andric       return REAL(func)(__VA_ARGS__);                                          \
68e8d8bef9SDimitry Andric     ENSURE_MEMPROF_INITED();                                                   \
69e8d8bef9SDimitry Andric   } while (false)
70e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path)                              \
71e8d8bef9SDimitry Andric   do {                                                                         \
72e8d8bef9SDimitry Andric   } while (false)
73e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd)                                 \
74e8d8bef9SDimitry Andric   do {                                                                         \
75e8d8bef9SDimitry Andric   } while (false)
76e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd)                                 \
77e8d8bef9SDimitry Andric   do {                                                                         \
78e8d8bef9SDimitry Andric   } while (false)
79e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd)                    \
80e8d8bef9SDimitry Andric   do {                                                                         \
81e8d8bef9SDimitry Andric   } while (false)
82e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name)
83e8d8bef9SDimitry Andric // Should be memprofThreadRegistry().SetThreadNameByUserId(thread, name)
84e8d8bef9SDimitry Andric // But memprof does not remember UserId's for threads (pthread_t);
85e8d8bef9SDimitry Andric // and remembers all ever existed threads, so the linear search by UserId
86e8d8bef9SDimitry Andric // can be slow.
87e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name)                 \
88e8d8bef9SDimitry Andric   do {                                                                         \
89e8d8bef9SDimitry Andric   } while (false)
90e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
91e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
92e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)
93e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()
94e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!memprof_inited)
95e8d8bef9SDimitry Andric #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
96e8d8bef9SDimitry Andric   if (MemprofThread *t = GetCurrentThread()) {                                 \
97e8d8bef9SDimitry Andric     *begin = t->tls_begin();                                                   \
98e8d8bef9SDimitry Andric     *end = t->tls_end();                                                       \
99e8d8bef9SDimitry Andric   } else {                                                                     \
100e8d8bef9SDimitry Andric     *begin = *end = 0;                                                         \
101e8d8bef9SDimitry Andric   }
102e8d8bef9SDimitry Andric 
103e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_common_interceptors.inc"
104e8d8bef9SDimitry Andric 
105e8d8bef9SDimitry Andric #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) MEMPROF_READ_RANGE(p, s)
106e8d8bef9SDimitry Andric #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) MEMPROF_WRITE_RANGE(p, s)
107e8d8bef9SDimitry Andric #define COMMON_SYSCALL_POST_READ_RANGE(p, s)                                   \
108e8d8bef9SDimitry Andric   do {                                                                         \
109e8d8bef9SDimitry Andric     (void)(p);                                                                 \
110e8d8bef9SDimitry Andric     (void)(s);                                                                 \
111e8d8bef9SDimitry Andric   } while (false)
112e8d8bef9SDimitry Andric #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s)                                  \
113e8d8bef9SDimitry Andric   do {                                                                         \
114e8d8bef9SDimitry Andric     (void)(p);                                                                 \
115e8d8bef9SDimitry Andric     (void)(s);                                                                 \
116e8d8bef9SDimitry Andric   } while (false)
117e8d8bef9SDimitry Andric #include "sanitizer_common/sanitizer_common_syscalls.inc"
118e8d8bef9SDimitry Andric 
119e8d8bef9SDimitry Andric struct ThreadStartParam {
120e8d8bef9SDimitry Andric   atomic_uintptr_t t;
121e8d8bef9SDimitry Andric   atomic_uintptr_t is_registered;
122e8d8bef9SDimitry Andric };
123e8d8bef9SDimitry Andric 
124e8d8bef9SDimitry Andric static thread_return_t THREAD_CALLING_CONV memprof_thread_start(void *arg) {
125e8d8bef9SDimitry Andric   ThreadStartParam *param = reinterpret_cast<ThreadStartParam *>(arg);
126e8d8bef9SDimitry Andric   MemprofThread *t = nullptr;
127e8d8bef9SDimitry Andric   while ((t = reinterpret_cast<MemprofThread *>(
128e8d8bef9SDimitry Andric               atomic_load(&param->t, memory_order_acquire))) == nullptr)
129e8d8bef9SDimitry Andric     internal_sched_yield();
130e8d8bef9SDimitry Andric   SetCurrentThread(t);
131e8d8bef9SDimitry Andric   return t->ThreadStart(GetTid(), &param->is_registered);
132e8d8bef9SDimitry Andric }
133e8d8bef9SDimitry Andric 
134e8d8bef9SDimitry Andric INTERCEPTOR(int, pthread_create, void *thread, void *attr,
135e8d8bef9SDimitry Andric             void *(*start_routine)(void *), void *arg) {
136e8d8bef9SDimitry Andric   EnsureMainThreadIDIsCorrect();
137e8d8bef9SDimitry Andric   GET_STACK_TRACE_THREAD;
138e8d8bef9SDimitry Andric   int detached = 0;
139e8d8bef9SDimitry Andric   if (attr)
140e8d8bef9SDimitry Andric     REAL(pthread_attr_getdetachstate)(attr, &detached);
141e8d8bef9SDimitry Andric   ThreadStartParam param;
142e8d8bef9SDimitry Andric   atomic_store(&param.t, 0, memory_order_relaxed);
143e8d8bef9SDimitry Andric   atomic_store(&param.is_registered, 0, memory_order_relaxed);
144e8d8bef9SDimitry Andric   int result;
145e8d8bef9SDimitry Andric   {
146e8d8bef9SDimitry Andric     // Ignore all allocations made by pthread_create: thread stack/TLS may be
147e8d8bef9SDimitry Andric     // stored by pthread for future reuse even after thread destruction, and
148e8d8bef9SDimitry Andric     // the linked list it's stored in doesn't even hold valid pointers to the
149e8d8bef9SDimitry Andric     // objects, the latter are calculated by obscure pointer arithmetic.
150e8d8bef9SDimitry Andric     result = REAL(pthread_create)(thread, attr, memprof_thread_start, &param);
151e8d8bef9SDimitry Andric   }
152e8d8bef9SDimitry Andric   if (result == 0) {
153e8d8bef9SDimitry Andric     u32 current_tid = GetCurrentTidOrInvalid();
154e8d8bef9SDimitry Andric     MemprofThread *t = MemprofThread::Create(start_routine, arg, current_tid,
155e8d8bef9SDimitry Andric                                              &stack, detached);
156e8d8bef9SDimitry Andric     atomic_store(&param.t, reinterpret_cast<uptr>(t), memory_order_release);
157e8d8bef9SDimitry Andric     // Wait until the MemprofThread object is initialized and the
158e8d8bef9SDimitry Andric     // ThreadRegistry entry is in "started" state.
159e8d8bef9SDimitry Andric     while (atomic_load(&param.is_registered, memory_order_acquire) == 0)
160e8d8bef9SDimitry Andric       internal_sched_yield();
161e8d8bef9SDimitry Andric   }
162e8d8bef9SDimitry Andric   return result;
163e8d8bef9SDimitry Andric }
164e8d8bef9SDimitry Andric 
165e8d8bef9SDimitry Andric INTERCEPTOR(int, pthread_join, void *t, void **arg) {
166*0fca6ea1SDimitry Andric   return REAL(pthread_join)(t, arg);
167e8d8bef9SDimitry Andric }
168e8d8bef9SDimitry Andric 
169*0fca6ea1SDimitry Andric DEFINE_INTERNAL_PTHREAD_FUNCTIONS
170e8d8bef9SDimitry Andric 
171e8d8bef9SDimitry Andric INTERCEPTOR(char *, index, const char *string, int c)
17206c3fb27SDimitry Andric ALIAS(WRAP(strchr));
173e8d8bef9SDimitry Andric 
174e8d8bef9SDimitry Andric // For both strcat() and strncat() we need to check the validity of |to|
175e8d8bef9SDimitry Andric // argument irrespective of the |from| length.
176e8d8bef9SDimitry Andric INTERCEPTOR(char *, strcat, char *to, const char *from) {
177e8d8bef9SDimitry Andric   void *ctx;
178e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strcat);
179e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
180349cc55cSDimitry Andric   uptr from_length = internal_strlen(from);
181e8d8bef9SDimitry Andric   MEMPROF_READ_RANGE(from, from_length + 1);
182349cc55cSDimitry Andric   uptr to_length = internal_strlen(to);
183e8d8bef9SDimitry Andric   MEMPROF_READ_STRING(to, to_length);
184e8d8bef9SDimitry Andric   MEMPROF_WRITE_RANGE(to + to_length, from_length + 1);
185e8d8bef9SDimitry Andric   return REAL(strcat)(to, from);
186e8d8bef9SDimitry Andric }
187e8d8bef9SDimitry Andric 
188e8d8bef9SDimitry Andric INTERCEPTOR(char *, strncat, char *to, const char *from, uptr size) {
189e8d8bef9SDimitry Andric   void *ctx;
190e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strncat);
191e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
192e8d8bef9SDimitry Andric   uptr from_length = MaybeRealStrnlen(from, size);
193e8d8bef9SDimitry Andric   uptr copy_length = Min(size, from_length + 1);
194e8d8bef9SDimitry Andric   MEMPROF_READ_RANGE(from, copy_length);
195349cc55cSDimitry Andric   uptr to_length = internal_strlen(to);
196e8d8bef9SDimitry Andric   MEMPROF_READ_STRING(to, to_length);
197e8d8bef9SDimitry Andric   MEMPROF_WRITE_RANGE(to + to_length, from_length + 1);
198e8d8bef9SDimitry Andric   return REAL(strncat)(to, from, size);
199e8d8bef9SDimitry Andric }
200e8d8bef9SDimitry Andric 
201e8d8bef9SDimitry Andric INTERCEPTOR(char *, strcpy, char *to, const char *from) {
202e8d8bef9SDimitry Andric   void *ctx;
203e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strcpy);
204e8d8bef9SDimitry Andric   if (memprof_init_is_running) {
205e8d8bef9SDimitry Andric     return REAL(strcpy)(to, from);
206e8d8bef9SDimitry Andric   }
207e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
208349cc55cSDimitry Andric   uptr from_size = internal_strlen(from) + 1;
209e8d8bef9SDimitry Andric   MEMPROF_READ_RANGE(from, from_size);
210e8d8bef9SDimitry Andric   MEMPROF_WRITE_RANGE(to, from_size);
211e8d8bef9SDimitry Andric   return REAL(strcpy)(to, from);
212e8d8bef9SDimitry Andric }
213e8d8bef9SDimitry Andric 
214e8d8bef9SDimitry Andric INTERCEPTOR(char *, strdup, const char *s) {
215e8d8bef9SDimitry Andric   void *ctx;
216e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strdup);
217e8d8bef9SDimitry Andric   if (UNLIKELY(!memprof_inited))
218e8d8bef9SDimitry Andric     return internal_strdup(s);
219e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
220349cc55cSDimitry Andric   uptr length = internal_strlen(s);
221e8d8bef9SDimitry Andric   MEMPROF_READ_RANGE(s, length + 1);
222e8d8bef9SDimitry Andric   GET_STACK_TRACE_MALLOC;
223e8d8bef9SDimitry Andric   void *new_mem = memprof_malloc(length + 1, &stack);
224e8d8bef9SDimitry Andric   REAL(memcpy)(new_mem, s, length + 1);
225e8d8bef9SDimitry Andric   return reinterpret_cast<char *>(new_mem);
226e8d8bef9SDimitry Andric }
227e8d8bef9SDimitry Andric 
228e8d8bef9SDimitry Andric INTERCEPTOR(char *, __strdup, const char *s) {
229e8d8bef9SDimitry Andric   void *ctx;
230e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strdup);
231e8d8bef9SDimitry Andric   if (UNLIKELY(!memprof_inited))
232e8d8bef9SDimitry Andric     return internal_strdup(s);
233e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
234349cc55cSDimitry Andric   uptr length = internal_strlen(s);
235e8d8bef9SDimitry Andric   MEMPROF_READ_RANGE(s, length + 1);
236e8d8bef9SDimitry Andric   GET_STACK_TRACE_MALLOC;
237e8d8bef9SDimitry Andric   void *new_mem = memprof_malloc(length + 1, &stack);
238e8d8bef9SDimitry Andric   REAL(memcpy)(new_mem, s, length + 1);
239e8d8bef9SDimitry Andric   return reinterpret_cast<char *>(new_mem);
240e8d8bef9SDimitry Andric }
241e8d8bef9SDimitry Andric 
242e8d8bef9SDimitry Andric INTERCEPTOR(char *, strncpy, char *to, const char *from, uptr size) {
243e8d8bef9SDimitry Andric   void *ctx;
244e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strncpy);
245e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
246e8d8bef9SDimitry Andric   uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1);
247e8d8bef9SDimitry Andric   MEMPROF_READ_RANGE(from, from_size);
248e8d8bef9SDimitry Andric   MEMPROF_WRITE_RANGE(to, size);
249e8d8bef9SDimitry Andric   return REAL(strncpy)(to, from, size);
250e8d8bef9SDimitry Andric }
251e8d8bef9SDimitry Andric 
252e8d8bef9SDimitry Andric INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
253e8d8bef9SDimitry Andric   void *ctx;
254e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strtol);
255e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
256e8d8bef9SDimitry Andric   char *real_endptr;
257e8d8bef9SDimitry Andric   long result = REAL(strtol)(nptr, &real_endptr, base);
258e8d8bef9SDimitry Andric   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
259e8d8bef9SDimitry Andric   return result;
260e8d8bef9SDimitry Andric }
261e8d8bef9SDimitry Andric 
262e8d8bef9SDimitry Andric INTERCEPTOR(int, atoi, const char *nptr) {
263e8d8bef9SDimitry Andric   void *ctx;
264e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, atoi);
265e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
266e8d8bef9SDimitry Andric   char *real_endptr;
267e8d8bef9SDimitry Andric   // "man atoi" tells that behavior of atoi(nptr) is the same as
268e8d8bef9SDimitry Andric   // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the
269e8d8bef9SDimitry Andric   // parsed integer can't be stored in *long* type (even if it's
270e8d8bef9SDimitry Andric   // different from int). So, we just imitate this behavior.
271e8d8bef9SDimitry Andric   int result = REAL(strtol)(nptr, &real_endptr, 10);
272e8d8bef9SDimitry Andric   FixRealStrtolEndptr(nptr, &real_endptr);
273e8d8bef9SDimitry Andric   MEMPROF_READ_STRING(nptr, (real_endptr - nptr) + 1);
274e8d8bef9SDimitry Andric   return result;
275e8d8bef9SDimitry Andric }
276e8d8bef9SDimitry Andric 
277e8d8bef9SDimitry Andric INTERCEPTOR(long, atol, const char *nptr) {
278e8d8bef9SDimitry Andric   void *ctx;
279e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, atol);
280e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
281e8d8bef9SDimitry Andric   char *real_endptr;
282e8d8bef9SDimitry Andric   long result = REAL(strtol)(nptr, &real_endptr, 10);
283e8d8bef9SDimitry Andric   FixRealStrtolEndptr(nptr, &real_endptr);
284e8d8bef9SDimitry Andric   MEMPROF_READ_STRING(nptr, (real_endptr - nptr) + 1);
285e8d8bef9SDimitry Andric   return result;
286e8d8bef9SDimitry Andric }
287e8d8bef9SDimitry Andric 
288e8d8bef9SDimitry Andric INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
289e8d8bef9SDimitry Andric   void *ctx;
290e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, strtoll);
291e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
292e8d8bef9SDimitry Andric   char *real_endptr;
293e8d8bef9SDimitry Andric   long long result = REAL(strtoll)(nptr, &real_endptr, base);
294e8d8bef9SDimitry Andric   StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
295e8d8bef9SDimitry Andric   return result;
296e8d8bef9SDimitry Andric }
297e8d8bef9SDimitry Andric 
298e8d8bef9SDimitry Andric INTERCEPTOR(long long, atoll, const char *nptr) {
299e8d8bef9SDimitry Andric   void *ctx;
300e8d8bef9SDimitry Andric   MEMPROF_INTERCEPTOR_ENTER(ctx, atoll);
301e8d8bef9SDimitry Andric   ENSURE_MEMPROF_INITED();
302e8d8bef9SDimitry Andric   char *real_endptr;
303e8d8bef9SDimitry Andric   long long result = REAL(strtoll)(nptr, &real_endptr, 10);
304e8d8bef9SDimitry Andric   FixRealStrtolEndptr(nptr, &real_endptr);
305e8d8bef9SDimitry Andric   MEMPROF_READ_STRING(nptr, (real_endptr - nptr) + 1);
306e8d8bef9SDimitry Andric   return result;
307e8d8bef9SDimitry Andric }
308e8d8bef9SDimitry Andric 
309e8d8bef9SDimitry Andric // ---------------------- InitializeMemprofInterceptors ---------------- {{{1
310e8d8bef9SDimitry Andric namespace __memprof {
311e8d8bef9SDimitry Andric void InitializeMemprofInterceptors() {
312e8d8bef9SDimitry Andric   static bool was_called_once;
313e8d8bef9SDimitry Andric   CHECK(!was_called_once);
314e8d8bef9SDimitry Andric   was_called_once = true;
315e8d8bef9SDimitry Andric   InitializeCommonInterceptors();
316e8d8bef9SDimitry Andric 
317e8d8bef9SDimitry Andric   // Intercept str* functions.
318e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(strcat);
319e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(strcpy);
320e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(strncat);
321e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(strncpy);
322e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(strdup);
323e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(__strdup);
324e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(index);
325e8d8bef9SDimitry Andric 
326e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(atoi);
327e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(atol);
328e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(strtol);
329e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(atoll);
330e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(strtoll);
331e8d8bef9SDimitry Andric 
332e8d8bef9SDimitry Andric   // Intercept threading-related functions
333e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(pthread_create);
334e8d8bef9SDimitry Andric   MEMPROF_INTERCEPT_FUNC(pthread_join);
335e8d8bef9SDimitry Andric 
336e8d8bef9SDimitry Andric   InitializePlatformInterceptors();
337e8d8bef9SDimitry Andric 
338e8d8bef9SDimitry Andric   VReport(1, "MemProfiler: libc interceptors initialized\n");
339e8d8bef9SDimitry Andric }
340e8d8bef9SDimitry Andric 
341e8d8bef9SDimitry Andric } // namespace __memprof
342