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