Warning, file /sdk/heaptrack/src/track/heaptrack_api.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2016-2017 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 /**
0008  * @file heaptrack_api.h
0009  *
0010  * This file defines a public API for heaptrack to be used in applications and
0011  * libraries that implement custom allocators that do not use malloc internally.
0012  *
0013  * It should be enough to include this header in your code and then add calls
0014  * to @c heaptrack_report_alloc, @c heaptrack_report_realloc and
0015  * @c heaptrack_report_free to your code. By default, nothing will happen.
0016  * Once you run your code within heaptrack though, this information will be
0017  * picked up and included in the heap profile data.
0018  *
0019  * Note: If you use static linking, or have a custom allocator in your main
0020  * executable, then you must define HEAPTRACK_API_DLSYM before including
0021  * this header and link against libdl to make this work properly. The other,
0022  * more common, case of pool allocators in shared libraries will work with the
0023  * default implementation that relies on weak symbols and the dynamic linker
0024  * on resolving the symbols for us directly.
0025  */
0026 
0027 #ifndef HEAPTRACK_API_H
0028 #define HEAPTRACK_API_H
0029 
0030 #include <stdlib.h>
0031 
0032 #ifndef HEAPTRACK_API_DLSYM
0033 
0034 /**
0035  * By default we rely on weak symbols that get resolved by the dynamic linker.
0036  * The weak symbols defined here are usually zero, but become non-zero when
0037  * we run the application with libheaptrack_preload.so loaded in.
0038  *
0039  * Note that this does not support run-time attaching yet.
0040  * Also note that this won't work inside your main executable, nor when you use
0041  * static linking. In these cases, the dlsym code below should be used instead.
0042  */
0043 
0044 #ifdef __cplusplus
0045 extern "C" {
0046 #endif
0047 
0048 __attribute__((weak)) void heaptrack_malloc(void* ptr, size_t size);
0049 __attribute__((weak)) void heaptrack_realloc(void* ptr_in, size_t size, void* ptr_out);
0050 __attribute__((weak)) void heaptrack_free(void* ptr);
0051 
0052 #ifdef __cplusplus
0053 }
0054 #endif
0055 
0056 #define heaptrack_report_alloc(ptr, size)                                                                              \
0057     if (heaptrack_malloc)                                                                                              \
0058     heaptrack_malloc(ptr, size)
0059 
0060 #define heaptrack_report_realloc(ptr_in, size, ptr_out)                                                                \
0061     if (heaptrack_realloc)                                                                                             \
0062     heaptrack_realloc(ptr_in, size, ptr_out)
0063 
0064 #define heaptrack_report_free(ptr)                                                                                     \
0065     if (heaptrack_free)                                                                                                \
0066     heaptrack_free(ptr)
0067 
0068 #else // HEAPTRACK_API_DLSYM
0069 
0070 /**
0071  * Alternatively, we rely on dlsym to dynamically resolve the symbol to the
0072  * heaptrack API functions at runtime. This works reliably, also when using
0073  * static linking or when calling these functions from within your main
0074  * executable. The caveat is that you need to link to libdl dynamically.
0075  *
0076  * @code
0077  *
0078  *   gcc -DHEAPTRACK_API_DLSYM=1 -ldl ...
0079  * @endcode
0080  */
0081 
0082 #ifndef __USE_GNU
0083 // required for RTLD_NEXT
0084 #define __USE_GNU
0085 #endif
0086 
0087 #include <dlfcn.h>
0088 
0089 struct heaptrack_api_t
0090 {
0091     void (*malloc)(void*, size_t);
0092     void (*free)(void*);
0093     void (*realloc)(void*, size_t, void*);
0094 };
0095 static struct heaptrack_api_t heaptrack_api = {0, 0, 0};
0096 
0097 void heaptrack_init_api()
0098 {
0099     static int initialized = 0;
0100     if (!initialized) {
0101         void* sym = dlsym(RTLD_NEXT, "heaptrack_malloc");
0102         if (sym)
0103             heaptrack_api.malloc = (void (*)(void*, size_t))sym;
0104 
0105         sym = dlsym(RTLD_NEXT, "heaptrack_realloc");
0106         if (sym)
0107             heaptrack_api.realloc = (void (*)(void*, size_t, void*))sym;
0108 
0109         sym = dlsym(RTLD_NEXT, "heaptrack_free");
0110         if (sym)
0111             heaptrack_api.free = (void (*)(void*))sym;
0112 
0113         initialized = 1;
0114     }
0115 }
0116 
0117 #define heaptrack_report_alloc(ptr, size)                                                                              \
0118     do {                                                                                                               \
0119         heaptrack_init_api();                                                                                          \
0120         if (heaptrack_api.malloc)                                                                                      \
0121             heaptrack_api.malloc(ptr, size);                                                                           \
0122     } while (0)
0123 
0124 #define heaptrack_report_realloc(ptr_in, size, ptr_out)                                                                \
0125     do {                                                                                                               \
0126         heaptrack_init_api();                                                                                          \
0127         if (heaptrack_api.realloc)                                                                                     \
0128             heaptrack_api.realloc(ptr_in, size, ptr_out);                                                              \
0129     } while (0)
0130 
0131 #define heaptrack_report_free(ptr)                                                                                     \
0132     do {                                                                                                               \
0133         heaptrack_init_api();                                                                                          \
0134         if (heaptrack_api.free)                                                                                        \
0135             heaptrack_api.free(ptr);                                                                                   \
0136     } while (0)
0137 
0138 #endif // HEAPTRACK_API_DLSYM
0139 
0140 /**
0141  * Optionally, you can let heaptrack mimick the Valgrind pool-allocator API.
0142  *
0143  * This won't work nicely when you want to enable both, Valgrind and heaptrack.
0144  * Otherwise, it's an easy way to make your code ready for both tools.
0145  */
0146 #ifdef HEAPTRACK_DEFINE_VALGRIND_MACROS
0147 
0148 #define VALGRIND_DISABLE_ERROR_REPORTING
0149 #define VALGRIND_ENABLE_ERROR_REPORTING
0150 #define VALGRIND_CREATE_MEMPOOL(...)
0151 #define VALGRIND_DESTROY_MEMPOOL(...)
0152 #define VALGRIND_MAKE_MEM_NOACCESS(...)
0153 
0154 #define VALGRIND_MEMPOOL_ALLOC(pool, ptr, size) heaptrack_report_alloc(ptr, size)
0155 #define VALGRIND_MEMPOOL_FREE(pool, ptr) heaptrack_report_free(ptr)
0156 
0157 #endif
0158 
0159 #endif // HEAPTRACK_API_H