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