2 * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <ecoli_test.h>
34 #include <ecoli_malloc.h>
36 static const char ec_short_options[] =
42 EC_OPT_LONG_MIN_NUM = 256,
43 #define EC_OPT_HELP "help"
47 static const struct option ec_long_options[] = {
48 {EC_OPT_HELP, 1, NULL, EC_OPT_HELP_NUM},
52 static void usage(const char *prgname)
54 printf("%s [options]\n"
55 " --"EC_OPT_HELP": show this help\n"
59 static void parse_args(int argc, char **argv)
63 while ((opt = getopt_long(argc, argv, ec_short_options,
64 ec_long_options, NULL)) != EOF) {
79 TAILQ_HEAD(debug_alloc_hdr_list, debug_alloc_hdr);
80 static struct debug_alloc_hdr_list debug_alloc_hdr_list =
81 TAILQ_HEAD_INITIALIZER(debug_alloc_hdr_list);
83 struct debug_alloc_hdr {
84 TAILQ_ENTRY(debug_alloc_hdr) next;
91 struct debug_alloc_ftr {
93 } __attribute__((packed));
95 static void *debug_malloc(size_t size, const char *file, unsigned int line)
97 struct debug_alloc_hdr *hdr;
98 struct debug_alloc_ftr *ftr;
99 size_t new_size = size + sizeof(*hdr) + sizeof(*ftr);
102 hdr = malloc(new_size);
109 hdr->cookie = 0x12345678;
110 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, hdr, next);
112 ftr = (struct debug_alloc_ftr *)(
113 (char *)hdr + size + sizeof(*hdr));
114 ftr->cookie = 0x12345678;
117 ec_log(EC_LOG_INFO, "%s:%d: info: malloc(%zd) -> %p\n",
118 file, line, size, ret);
123 static void debug_free(void *ptr, const char *file, unsigned int line)
125 struct debug_alloc_hdr *hdr, *h;
126 struct debug_alloc_ftr *ftr;
131 ec_log(EC_LOG_INFO, "%s:%d: info: free(%p)\n", file, line, ptr);
136 hdr = (ptr - sizeof(*hdr));
137 if (hdr->cookie != 0x12345678) {
138 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad start cookie\n",
143 ftr = (ptr + hdr->size);
144 if (ftr->cookie != 0x12345678) {
145 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad end cookie\n",
150 TAILQ_FOREACH(h, &debug_alloc_hdr_list, next) {
156 ec_log(EC_LOG_ERR, "%s:%d: error: free(%p): bad ptr\n",
161 TAILQ_REMOVE(&debug_alloc_hdr_list, hdr, next);
165 void *debug_realloc(void *ptr, size_t size, const char *file, unsigned int line)
167 struct debug_alloc_hdr *hdr, *h;
168 struct debug_alloc_ftr *ftr;
169 size_t new_size = size + sizeof(*hdr) + sizeof(unsigned int);
173 hdr = (ptr - sizeof(*hdr));
174 if (hdr->cookie != 0x12345678) {
176 "%s:%d: error: realloc(%p): bad start cookie\n",
181 ftr = (ptr + hdr->size);
182 if (ftr->cookie != 0x12345678) {
184 "%s:%d: error: realloc(%p): bad end cookie\n",
189 TAILQ_FOREACH(h, &debug_alloc_hdr_list, next) {
195 ec_log(EC_LOG_ERR, "%s:%d: error: realloc(%p): bad ptr\n",
200 TAILQ_REMOVE(&debug_alloc_hdr_list, h, next);
201 hdr = realloc(hdr, new_size);
203 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, h, next);
209 hdr = realloc(NULL, new_size);
220 hdr->cookie = 0x12345678;
221 TAILQ_INSERT_TAIL(&debug_alloc_hdr_list, hdr, next);
222 ftr = (struct debug_alloc_ftr *)(
223 (char *)hdr + size + sizeof(*hdr));
224 ftr->cookie = 0x12345678;
227 ec_log(EC_LOG_INFO, "%s:%d: info: realloc(%p, %zd) -> %p\n",
228 file, line, ptr, size, ret);
233 void debug_alloc_dump(void)
235 struct debug_alloc_hdr *hdr;
237 TAILQ_FOREACH(hdr, &debug_alloc_hdr_list, next) {
238 ec_log(EC_LOG_ERR, "%s:%d: error: memory leak size=%zd ptr=%p\n",
239 hdr->file, hdr->line, hdr->size, hdr + 1);
243 int main(int argc, char **argv)
247 parse_args(argc, argv);
249 TAILQ_INIT(&debug_alloc_hdr_list);
250 /* register a new malloc to track memleaks */
251 if (ec_malloc_register(debug_malloc, debug_free, debug_realloc) < 0) {
252 ec_log(EC_LOG_ERR, "cannot register new malloc\n");
258 ec_malloc_unregister();
262 printf("tests failed\n");