]>
git.cameronkatri.com Git - mandoc.git/blob - mandoc_dbg.c
1 /* $Id: mandoc_dbg.c,v 1.1 2022/04/14 16:43:44 schwarze Exp $ */
3 * Copyright (c) 2021, 2022 Ingo Schwarze <schwarze@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
35 #include "compat_ohash.h"
39 #include "mandoc_aux.h"
42 /* Store information about one allocation. */
52 /* Store information about all allocations. */
53 static struct ohash dhash_table
;
54 static FILE *dhash_fp
;
55 static int dhash_aflag
;
56 static int dhash_fflag
;
57 static int dhash_lflag
;
58 static int dhash_nflag
;
59 static int dhash_sflag
;
61 static void *dhash_alloc(size_t, void *);
62 static void *dhash_calloc(size_t, size_t, void *);
63 static void dhash_free(void *, void *);
64 static unsigned int dhash_slot(void *);
65 static void dhash_register(const char *, int, const char *,
66 size_t, size_t, void *, const char *);
67 static void dhash_print(struct dhash_entry
*);
68 static void dhash_purge(const char *, int, const char *, void *);
71 /* *** Debugging wrappers of public API functions. ************************ */
74 mandoc_dbg_asprintf(const char *file
, int line
,
75 char **dest
, const char *fmt
, ...)
81 ret
= vasprintf(dest
, fmt
, ap
);
85 err((int)MANDOCLEVEL_SYSERR
, NULL
);
87 dhash_register(file
, line
, "asprintf", 1, strlen(*dest
) + 1,
94 mandoc_dbg_calloc(size_t num
, size_t size
, const char *file
, int line
)
96 void *ptr
= mandoc_calloc(num
, size
);
97 dhash_register(file
, line
, "calloc", num
, size
, ptr
, NULL
);
102 mandoc_dbg_malloc(size_t size
, const char *file
, int line
)
104 void *ptr
= mandoc_malloc(size
);
105 dhash_register(file
, line
, "malloc", 1, size
, ptr
, NULL
);
110 mandoc_dbg_realloc(void *ptr
, size_t size
, const char *file
, int line
)
112 dhash_purge(file
, line
, "realloc", ptr
);
113 ptr
= mandoc_realloc(ptr
, size
);
114 dhash_register(file
, line
, "realloc", 1, size
, ptr
, NULL
);
119 mandoc_dbg_reallocarray(void *ptr
, size_t num
, size_t size
,
120 const char *file
, int line
)
122 dhash_purge(file
, line
, "reallocarray", ptr
);
123 ptr
= mandoc_reallocarray(ptr
, num
, size
);
124 dhash_register(file
, line
, "reallocarray", num
, size
, ptr
, NULL
);
129 mandoc_dbg_recallocarray(void *ptr
, size_t oldnum
, size_t num
, size_t size
,
130 const char *file
, int line
)
132 dhash_purge(file
, line
, "recallocarray", ptr
);
133 ptr
= mandoc_recallocarray(ptr
, oldnum
, num
, size
);
134 dhash_register(file
, line
, "recallocarray", num
, size
, ptr
, NULL
);
139 mandoc_dbg_strdup(const char *ptr
, const char *file
, int line
)
141 char *p
= mandoc_strdup(ptr
);
142 dhash_register(file
, line
, "strdup", 1, strlen(p
) + 1, p
, ptr
);
147 mandoc_dbg_strndup(const char *ptr
, size_t sz
, const char *file
, int line
)
149 char *p
= mandoc_strndup(ptr
, sz
);
150 dhash_register(file
, line
, "strndup", 1, strlen(p
) + 1, p
, NULL
);
155 mandoc_dbg_free(void *ptr
, const char *file
, int line
)
157 dhash_purge(file
, line
, "free", ptr
);
162 /* *** Memory allocation callbacks for the debugging table. *************** */
165 dhash_alloc(size_t sz
, void *arg
)
171 dhash_calloc(size_t n
, size_t sz
, void *arg
)
173 return calloc(n
, sz
);
177 dhash_free(void *p
, void *arg
)
183 /* *** Debugging utility functions. *************************************** */
185 /* Initialize the debugging table, to be called from the top of main(). */
187 mandoc_dbg_init(int argc
, char *argv
[])
189 struct ohash_info info
;
193 info
.alloc
= dhash_alloc
;
194 info
.calloc
= dhash_calloc
;
195 info
.free
= dhash_free
;
197 info
.key_offset
= offsetof(struct dhash_entry
, ptr
);
198 ohash_init(&dhash_table
, 18, &info
);
201 if ((dhash_fn
= getenv("DEBUG_MEMORY")) == NULL
)
222 if ((dhash_fp
= fopen(dhash_fn
, "a+e")) == NULL
)
223 err((int)MANDOCLEVEL_SYSERR
, "%s", dhash_fn
);
226 errx((int)MANDOCLEVEL_BADARG
,
227 "invalid char '%c' in $DEBUG_MEMORY",
232 if (setvbuf(dhash_fp
, NULL
, _IOLBF
, 0) != 0)
233 err((int)MANDOCLEVEL_SYSERR
, "setvbuf");
235 fprintf(dhash_fp
, "P %d", getpid());
236 for (argi
= 0; argi
< argc
; argi
++)
237 fprintf(dhash_fp
, " [%s]", argv
[argi
]);
238 fprintf(dhash_fp
, "\n");
242 mandoc_dbg_name(const char *name
)
245 fprintf(dhash_fp
, "N %s\n", name
);
248 /* Hash a pointer and return the table slot currently used for it. */
250 dhash_slot(void *ptr
)
255 ks
= (const char *)&ptr
;
256 ke
= ks
+ sizeof(ptr
);
257 hv
= ohash_interval(ks
, &ke
);
258 return ohash_lookup_memory(&dhash_table
, ks
, sizeof(ptr
), hv
);
261 /* Record one allocation in the debugging table. */
263 dhash_register(const char *file
, int line
, const char *func
,
264 size_t num
, size_t size
, void *ptr
, const char *str
)
266 struct dhash_entry
*e
;
269 slot
= dhash_slot(ptr
);
270 e
= ohash_find(&dhash_table
, slot
);
271 if (dhash_aflag
|| e
!= NULL
) {
272 fprintf(dhash_fp
, "A %s:%d %s(%zu, %zu) = %p",
273 file
, line
, func
, num
, size
, ptr
);
275 fprintf(dhash_fp
, " \"%s\"", str
);
276 fprintf(dhash_fp
, "\n");
280 fprintf(dhash_fp
, "E duplicate address %p\n", e
->ptr
);
281 errx((int)MANDOCLEVEL_BADARG
, "duplicate address %p", e
->ptr
);
284 if ((e
= malloc(sizeof(*e
))) == NULL
)
293 ohash_insert(&dhash_table
, slot
, e
);
296 /* Remove one allocation from the debugging table. */
298 dhash_purge(const char *file
, int line
, const char *func
, void *ptr
)
300 struct dhash_entry
*e
;
307 fprintf(dhash_fp
, "F %s:%d %s(%p)\n", file
, line
, func
, ptr
);
309 slot
= dhash_slot(ptr
);
310 e
= ohash_remove(&dhash_table
, slot
);
314 /* Pretty-print information about one allocation. */
316 dhash_print(struct dhash_entry
*e
)
318 fprintf(dhash_fp
, "L %s:%d %s(%zu, %zu) = %p\n",
319 e
->file
, e
->line
, e
->func
, e
->num
, e
->size
, e
->ptr
);
322 /* Pretty-print information about all active allocations. */
324 mandoc_dbg_finish(void)
326 struct dhash_entry
*e
;
327 unsigned int errcount
, slot
;
329 errcount
= ohash_entries(&dhash_table
);
330 e
= ohash_first(&dhash_table
, &slot
);
335 e
= ohash_next(&dhash_table
, &slot
);
337 ohash_delete(&dhash_table
);
339 fprintf(dhash_fp
, "S %u memory leaks found\n", errcount
);
340 if (dhash_fp
!= stderr
)