1 /*------------------------------------------------------------------------------ 2 * 3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved. 4 * The YADIFA TM software product is provided under the BSD 3-clause license: 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * * Neither the name of EURid nor the names of its contributors may be 16 * used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 *------------------------------------------------------------------------------ 32 * 33 */ 34 35 /** @defgroup debug Debug functions 36 * @ingroup dnscore 37 * @brief Debug functions. 38 * 39 * Definitions of debug functions/hooks, mainly memory related. 40 * 41 * THIS MEMORY DEBUGGER MUST BE INCLUDED WITH EVERY SINGLE (C) FILE. 42 * IF DEBUGGING MEMORY ALLOCATION IS USED, IT HAS TO BE ENABLED EVERYWHERE OR NOWHERE. 43 * 44 * @{ 45 */ 46 #ifndef _DEBUG_H 47 #define _DEBUG_H 48 49 #include <dnscore/dnscore-config-features.h> 50 51 #ifndef _SYSTYPES_H 52 #error PLEASE DO NOT INCLUDE debug.h DIRECTLY. USE sys_types.h. 53 #endif 54 55 #define DEBUG_STAT_SIZES 1 // Common 56 #define DEBUG_STAT_TAGS 2 // Usefull 57 #define DEBUG_STAT_DUMP 4 // USE WITH CARE 58 #define DEBUG_STAT_WALK 8 59 #define DEBUG_STAT_MMAP 16 60 61 #include <stdlib.h> 62 #include <stdio.h> 63 #include <assert.h> 64 /** @note : DO NOT INCLUDE THIS HERE WITHOUT SOME KIND OF PROTECTION #include <dnscore/format.h> */ 65 66 #include <dnscore/debug_config.h> 67 68 #if DNSCORE_HAS_MMAP_DEBUG_SUPPORT 69 // MUST be included before else the defines will break the build 70 #include <sys/mman.h> 71 72 //#pragma message("MMAP REROUTED") 73 void* debug_mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); 74 int debug_munmap(void *addr, size_t len); 75 void debug_mmap_stat(); 76 77 #define mmap(addr__,len__,prot__,flags__,fildes__,off__) debug_mmap((addr__),(len__),(prot__),(flags__),(fildes__),(off__)) 78 #define munmap(addr__,len__) debug_munmap((addr__),(len__)) 79 #endif 80 81 #if DEBUG 82 #include <dnscore/thread.h> 83 #endif 84 85 #if !DEBUG 86 #define yassert(x) 87 #else 88 void log_assert__(bool b, const char *txt, const char *file, int line); 89 #if !__clang_analyzer__ 90 #define yassert(cond__) log_assert__((cond__), #cond__, __FILE__, __LINE__);assert((cond__)) 91 #else 92 #define yassert(cond__) assert(cond__) 93 #endif 94 #endif 95 96 #ifdef __cplusplus 97 extern "C" { 98 #endif 99 100 #define GENERIC_TAG 0x434952454e4547 /* GENERIC */ 101 #define ZDB_STRDUP_TAG 0x505544525453 /* "STRDUP" */ 102 103 void debug_dump(void* data_pointer_,size_t size,size_t line_size,bool hex,bool text); 104 void debug_dump_ex(void* data_pointer_, size_t size_, size_t line_size, bool hex, bool text, bool address); 105 106 struct logger_handle; 107 108 bool debug_log_stacktrace(struct logger_handle *handle, u32 level, const char *prefix); 109 110 #if DEBUG 111 /* 112 * DO NOT FORGET THAT THE "L" FUNCTIONS DO REQUIRE A DEBUG_LEVEL #define 113 * BEFORE THE "debug.h" INCLUDE ! 114 */ 115 #define DEBUGLNF(...) osformatln(termerr,__VA_ARGS__) 116 #define DEBUGF(...) osformat(termerr,__VA_ARGS__) 117 #define OSDEBUG(term, ...) osformat((term),__VA_ARGS__) 118 #define LDEBUG(level, ...) if(DEBUG_LEVEL>=(level)) osformat(termerr,__VA_ARGS__) 119 #define OSLDEBUG(term, level, ...) if(DEBUG_LEVEL>=(level)) osformat((term),__VA_ARGS__) 120 #else 121 #define DEBUGLNF(...) 122 #define DEBUGF(...) 123 #define OSDEBUG(...) 124 #define LDEBUG(...) 125 #define OSLDEBUG(...) 126 #endif 127 128 #ifndef DNSCORE_HAS_MALLOC_DEBUG_SUPPORT 129 #error "bogus include sequence" 130 #endif 131 132 void debug_stat(int mask); 133 134 #if DNSCORE_HAS_MALLOC_DEBUG_SUPPORT 135 136 #ifndef MALLOC_OR_DIE 137 #error "something fishy is happening. MALLOC_OR_DIE has not been defined yet." 138 #endif 139 140 #ifndef REALLOC_OR_DIE 141 #error "something fishy is happening. REALLOC_OR_DIE has not been defined yet." 142 #endif 143 144 #undef MALLOC_OR_DIE 145 #undef REALLOC_OR_DIE 146 147 void* debug_malloc( 148 size_t size_,const char* file, int line 149 #if DNSCORE_DEBUG_HAS_BLOCK_TAG 150 ,u64 tag 151 #endif 152 ); 153 154 void* debug_calloc( 155 size_t size_,const char* file, int line 156 #if DNSCORE_DEBUG_HAS_BLOCK_TAG 157 ,u64 tag 158 #endif 159 ); 160 161 void* debug_realloc( 162 void* ptr_, 163 size_t size_, 164 const char* file, 165 int line 166 ); 167 168 bool debug_mallocated(void* ptr); 169 170 #define assert_mallocated(ptr) yassert(debug_mallocated(ptr)) 171 172 void debug_free(void* ptr,const char* file, int line); 173 void debug_mtest(void* ptr); 174 175 char* debug_strdup(const char*); 176 177 u32 debug_get_block_count(); 178 179 #ifdef strdup 180 #undef strdup 181 #endif 182 183 #define strdup debug_strdup 184 185 #if !DNSCORE_DEBUG_HAS_BLOCK_TAG 186 187 #define malloc(len__) debug_malloc((len__),__FILE__,__LINE__) 188 #define calloc(len__) debug_calloc((len__),__FILE__,__LINE__) 189 #define free(p__) debug_free((p__),__FILE__,__LINE__) 190 #define realloc(p__,len__) debug_realloc((p__),(len__),__FILE__,__LINE__) 191 192 #define MALLOC_OR_DIE(cast,target,size,tag) if(((target)=(cast)debug_malloc(size,__FILE__,__LINE__))==NULL){perror(__FILE__);abort(); /* NOT TAGGED*/ } 193 #define REALLOC_OR_DIE(cast,src_and_target,newsize,tag) if(((src_and_target)=(cast)debug_realloc((src_and_target),(newsize),__FILE__,__LINE__))==NULL){perror(__FILE__);abort(); /* NOT TAGGED */ } 194 #else 195 196 #define DBGALLOC_TAG 0x434f4c4c41474244 197 198 #define malloc(len__) debug_malloc((len__),__FILE__,__LINE__,DBGALLOC_TAG) 199 #define free(p__) debug_free((p__),__FILE__,__LINE__) 200 #define realloc(p__,len__) debug_realloc((p__),(len__),__FILE__,__LINE__) 201 202 #define MALLOC_OR_DIE(cast,target,size,tag) if(((target)=(cast)debug_malloc(size,__FILE__,__LINE__,(tag)))==NULL){perror(__FILE__);abort(); /* TAGGED */} 203 #define REALLOC_OR_DIE(cast,src_and_target,newsize,tag) if(((src_and_target)=(cast)debug_realloc((src_and_target),(newsize),__FILE__,__LINE__))==NULL){perror(__FILE__);abort(); /* NOT TAGGED */ } 204 #endif 205 206 #else 207 208 #define debug_mtest(x) 209 #define debug_mallocated(x) TRUE 210 #define assert_mallocated(x) 211 212 #if !(DNSCORE_HAS_MALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_DEBUG_SUPPORT || DNSCORE_HAS_ZALLOC_STATISTICS_SUPPORT || DNSCORE_HAS_MMAP_DEBUG_SUPPORT) 213 #define debug_stat(x) 214 #endif 215 216 /* 217 * MALLOC_OR_DIE and REALLOC_OR_DIE have already been defined in sys_types.h 218 */ 219 220 #endif 221 222 struct debug_bench_s 223 { 224 struct debug_bench_s *next; 225 const char *name; 226 u64 time_min; 227 u64 time_max; 228 u64 time_total; 229 u64 time_count; 230 }; 231 232 typedef struct debug_bench_s debug_bench_s; 233 234 struct output_stream; 235 struct logger_handle; 236 237 // declares timeus() 238 239 s64 timeus(); 240 241 void debug_bench_init(); 242 243 void debug_bench_register(debug_bench_s *bench, const char *name); 244 245 #define debug_bench_start(bench__) timeus() 246 247 #define debug_bench_stop(bench__, from__) debug_bench_commit((bench__), timeus() - (from__)); 248 249 void debug_bench_commit(debug_bench_s *bench, u64 delta); 250 void debug_bench_logdump_all(); 251 void debug_bench_print_all(struct output_stream *os); 252 253 void debug_bench_unregister_all(); 254 255 typedef intptr* stacktrace; 256 stacktrace debug_stacktrace_get(); 257 void debug_stacktrace_log(struct logger_handle *handle, u32 level, stacktrace trace); 258 void debug_stacktrace_log_with_prefix(struct logger_handle* handle, u32 level, stacktrace trace, const char *prefix); 259 void debug_stacktrace_try_log(struct logger_handle *handle, u32 level, stacktrace trace); 260 void debug_stacktrace_print(struct output_stream *os, stacktrace trace); 261 /** 262 * clears all stacktraces from memory 263 * should only be called at shutdown 264 */ 265 void debug_stacktrace_clear(); 266 267 #define UNICITY_DEFINE(x) 268 #define UNICITY_ACQUIRE(x) 269 #define UNICITY_RELEASE(x) 270 271 extern volatile size_t malloc_hook_total; 272 extern volatile size_t malloc_hook_malloc; 273 extern volatile size_t malloc_hook_free; 274 extern volatile size_t malloc_hook_realloc; 275 extern volatile size_t malloc_hook_memalign; 276 277 void debug_malloc_hooks_init(); 278 void debug_malloc_hooks_finalize(); 279 void *debug_malloc_unmonitored(size_t size); 280 void debug_free_unmonitored(void* ptr); 281 void debug_malloc_hook_tracked_dump(); 282 void debug_malloc_hook_caller_dump(); 283 void *debug_mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); 284 285 void debug_nop_hook(); // meant 286 287 struct debug_memory_by_tag_context_s; 288 typedef struct debug_memory_by_tag_context_s debug_memory_by_tag_context_t; 289 290 #if DNSCORE_DEBUG_HAS_BLOCK_TAG 291 debug_memory_by_tag_context_t* debug_memory_by_tag_new_instance(const char* name); 292 void debug_memory_by_tag_delete(debug_memory_by_tag_context_t *ctx); 293 void debug_memory_by_tag_init(debug_memory_by_tag_context_t *ctx, const char* name); 294 void debug_memory_by_tag_finalize(debug_memory_by_tag_context_t *ctx); 295 void debug_memory_by_tag_alloc_notify(debug_memory_by_tag_context_t *ctx, u64 tag, s64 size); 296 void debug_memory_by_tag_free_notify(debug_memory_by_tag_context_t *ctx, u64 tag, s64 size); 297 void debug_memory_by_tag_print(debug_memory_by_tag_context_t *ctx, struct output_stream *os); 298 #endif 299 300 #ifdef __cplusplus 301 } 302 #endif 303 304 #endif /* _DEBUG_H */ 305