xref: /illumos-gate/usr/src/lib/libdwarf/common/malloc_check.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
1bc1f688bSRobert Mustacchi /*
2bc1f688bSRobert Mustacchi 
3bc1f688bSRobert Mustacchi   Copyright (C) 2005 Silicon Graphics, Inc.  All Rights Reserved.
4bc1f688bSRobert Mustacchi 
5bc1f688bSRobert Mustacchi   This program is free software; you can redistribute it and/or modify it
6bc1f688bSRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
7bc1f688bSRobert Mustacchi   as published by the Free Software Foundation.
8bc1f688bSRobert Mustacchi 
9bc1f688bSRobert Mustacchi   This program is distributed in the hope that it would be useful, but
10bc1f688bSRobert Mustacchi   WITHOUT ANY WARRANTY; without even the implied warranty of
11bc1f688bSRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12bc1f688bSRobert Mustacchi 
13bc1f688bSRobert Mustacchi   Further, this software is distributed without any warranty that it is
14bc1f688bSRobert Mustacchi   free of the rightful claim of any third person regarding infringement
15bc1f688bSRobert Mustacchi   or the like.  Any license provided herein, whether implied or
16bc1f688bSRobert Mustacchi   otherwise, applies only to this software file.  Patent licenses, if
17bc1f688bSRobert Mustacchi   any, provided herein do not apply to combinations of this program with
18bc1f688bSRobert Mustacchi   other software, or any other product whatsoever.
19bc1f688bSRobert Mustacchi 
20bc1f688bSRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
21bc1f688bSRobert Mustacchi   License along with this program; if not, write the Free Software
22bc1f688bSRobert Mustacchi   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23bc1f688bSRobert Mustacchi   USA.
24bc1f688bSRobert Mustacchi 
25bc1f688bSRobert Mustacchi */
26bc1f688bSRobert Mustacchi 
27bc1f688bSRobert Mustacchi /* malloc_check.c For checking dealloc completeness.
28bc1f688bSRobert Mustacchi 
29bc1f688bSRobert Mustacchi    This code is as simple as possible and works ok for
30bc1f688bSRobert Mustacchi    reasonable size allocation counts.
31bc1f688bSRobert Mustacchi 
32bc1f688bSRobert Mustacchi    It treats allocation as global, and so will not
33bc1f688bSRobert Mustacchi    work very well if an application opens more than one
34bc1f688bSRobert Mustacchi    Dwarf_Debug.
35bc1f688bSRobert Mustacchi 
36bc1f688bSRobert Mustacchi */
37bc1f688bSRobert Mustacchi 
38bc1f688bSRobert Mustacchi #include <stdio.h>
39*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDLIB_H
40*4d9fdb46SRobert Mustacchi #include <stdlib.h>
41*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDLIB_H */
42*4d9fdb46SRobert Mustacchi #ifdef HAVE_MALLOC_H
43*4d9fdb46SRobert Mustacchi /* Useful include for some Windows compilers. */
44*4d9fdb46SRobert Mustacchi #include <malloc.h>
45*4d9fdb46SRobert Mustacchi #endif /* HAVE_MALLOC_H */
46bc1f688bSRobert Mustacchi #include "config.h"
47bc1f688bSRobert Mustacchi #include "dwarf_incl.h"
48bc1f688bSRobert Mustacchi #include "malloc_check.h"
49bc1f688bSRobert Mustacchi #ifdef  WANT_LIBBDWARF_MALLOC_CHECK
50bc1f688bSRobert Mustacchi 
51bc1f688bSRobert Mustacchi /*  To turn off printing every entry, just change the define
52bc1f688bSRobert Mustacchi     to set PRINT_MALLOC_DETAILS 0.
53bc1f688bSRobert Mustacchi */
54bc1f688bSRobert Mustacchi #define PRINT_MALLOC_DETAILS 0
55bc1f688bSRobert Mustacchi 
56bc1f688bSRobert Mustacchi #define MC_TYPE_UNKNOWN 0
57bc1f688bSRobert Mustacchi #define MC_TYPE_ALLOC 1
58bc1f688bSRobert Mustacchi #define MC_TYPE_DEALLOC 2
59bc1f688bSRobert Mustacchi 
60bc1f688bSRobert Mustacchi struct mc_data_s {
61bc1f688bSRobert Mustacchi     struct mc_data_s *mc_prev;
62bc1f688bSRobert Mustacchi     unsigned long mc_address;   /* Assumes this is large enough to hold
63bc1f688bSRobert Mustacchi         a pointer! */
64bc1f688bSRobert Mustacchi 
65bc1f688bSRobert Mustacchi     long mc_alloc_number;       /* Assigned in order by when record
66bc1f688bSRobert Mustacchi         created. */
67bc1f688bSRobert Mustacchi     unsigned char mc_alloc_code;        /* Allocation code, libdwarf. */
68bc1f688bSRobert Mustacchi     unsigned char mc_type;
69bc1f688bSRobert Mustacchi     unsigned char mc_dealloc_noted;     /* Used on an ALLOC node. */
70bc1f688bSRobert Mustacchi     unsigned char mc_dealloc_noted_count;       /* Used on an ALLOC
71bc1f688bSRobert Mustacchi         node. */
72bc1f688bSRobert Mustacchi };
73bc1f688bSRobert Mustacchi 
74bc1f688bSRobert Mustacchi /*
75bc1f688bSRobert Mustacchi 
76bc1f688bSRobert Mustacchi */
77bc1f688bSRobert Mustacchi #define HASH_TABLE_SIZE 10501
78bc1f688bSRobert Mustacchi static struct mc_data_s *mc_data_hash[HASH_TABLE_SIZE];
79bc1f688bSRobert Mustacchi static long mc_data_list_size = 0;
80bc1f688bSRobert Mustacchi 
81bc1f688bSRobert Mustacchi static char *alloc_type_name[MAX_DW_DLA + 1] = {
82bc1f688bSRobert Mustacchi     "",
83bc1f688bSRobert Mustacchi     "DW_DLA_STRING",
84bc1f688bSRobert Mustacchi     "DW_DLA_LOC",
85bc1f688bSRobert Mustacchi     "DW_DLA_LOCDESC",
86bc1f688bSRobert Mustacchi     "DW_DLA_ELLIST",
87bc1f688bSRobert Mustacchi     "DW_DLA_BOUNDS",
88bc1f688bSRobert Mustacchi     "DW_DLA_BLOCK",
89bc1f688bSRobert Mustacchi     "DW_DLA_DEBUG",
90bc1f688bSRobert Mustacchi     "DW_DLA_DIE",
91bc1f688bSRobert Mustacchi     "DW_DLA_LINE",
92bc1f688bSRobert Mustacchi     "DW_DLA_ATTR",
93bc1f688bSRobert Mustacchi     "DW_DLA_TYPE",
94bc1f688bSRobert Mustacchi     "DW_DLA_SUBSCR",
95bc1f688bSRobert Mustacchi     "DW_DLA_GLOBAL",
96bc1f688bSRobert Mustacchi     "DW_DLA_ERROR",
97bc1f688bSRobert Mustacchi     "DW_DLA_LIST",
98bc1f688bSRobert Mustacchi     "DW_DLA_LINEBUF",
99bc1f688bSRobert Mustacchi     "DW_DLA_ARANGE",
100bc1f688bSRobert Mustacchi     "DW_DLA_ABBREV",
101bc1f688bSRobert Mustacchi     "DW_DLA_FRAME_OP",
102bc1f688bSRobert Mustacchi     "DW_DLA_CIE",
103bc1f688bSRobert Mustacchi     "DW_DLA_FDE",
104bc1f688bSRobert Mustacchi     "DW_DLA_LOC_BLOCK",
105bc1f688bSRobert Mustacchi     "DW_DLA_FRAME_BLOCK",
106bc1f688bSRobert Mustacchi     "DW_DLA_FUNC",
107bc1f688bSRobert Mustacchi     "DW_DLA_TYPENAME",
108bc1f688bSRobert Mustacchi     "DW_DLA_VAR",
109bc1f688bSRobert Mustacchi     "DW_DLA_WEAK",
110bc1f688bSRobert Mustacchi     "DW_DLA_ADDR",
111bc1f688bSRobert Mustacchi     "DW_DLA_ABBREV_LIST",
112bc1f688bSRobert Mustacchi     "DW_DLA_CHAIN",
113bc1f688bSRobert Mustacchi     "DW_DLA_CU_CONTEXT",
114bc1f688bSRobert Mustacchi     "DW_DLA_FRAME",
115bc1f688bSRobert Mustacchi     "DW_DLA_GLOBAL_CONTEXT",
116bc1f688bSRobert Mustacchi     "DW_DLA_FILE_ENTRY",
117bc1f688bSRobert Mustacchi     "DW_DLA_LINE_CONTEXT",
118bc1f688bSRobert Mustacchi     "DW_DLA_LOC_CHAIN",
119bc1f688bSRobert Mustacchi     "DW_DLA_HASH_TABLE",
120bc1f688bSRobert Mustacchi     "DW_DLA_FUNC_CONTEXT",
121bc1f688bSRobert Mustacchi     "DW_DLA_TYPENAME_CONTEXT",
122bc1f688bSRobert Mustacchi     "DW_DLA_VAR_CONTEXT",
123bc1f688bSRobert Mustacchi     "DW_DLA_WEAK_CONTEXT",
124bc1f688bSRobert Mustacchi     "DW_DLA_PUBTYPES_CONTEXT"
125bc1f688bSRobert Mustacchi     /*  Don't forget to expand this list if the list of codes
126bc1f688bSRobert Mustacchi         expands. */
127bc1f688bSRobert Mustacchi };
128bc1f688bSRobert Mustacchi 
129bc1f688bSRobert Mustacchi static unsigned
hash_address(unsigned long addr)130bc1f688bSRobert Mustacchi hash_address(unsigned long addr)
131bc1f688bSRobert Mustacchi {
132bc1f688bSRobert Mustacchi     unsigned long a = addr >> 2;
133bc1f688bSRobert Mustacchi 
134bc1f688bSRobert Mustacchi     return a % HASH_TABLE_SIZE;
135bc1f688bSRobert Mustacchi }
136bc1f688bSRobert Mustacchi 
137bc1f688bSRobert Mustacchi #if PRINT_MALLOC_DETAILS
138bc1f688bSRobert Mustacchi static void
print_alloc_dealloc_detail(unsigned long addr,int code,char * whichisit)139bc1f688bSRobert Mustacchi print_alloc_dealloc_detail(unsigned long addr,
140bc1f688bSRobert Mustacchi     int code, char *whichisit)
141bc1f688bSRobert Mustacchi {
142bc1f688bSRobert Mustacchi     fprintf(stderr,
143bc1f688bSRobert Mustacchi         "%s  addr 0x%lx code %d (%s) entry %ld\n",
144bc1f688bSRobert Mustacchi         whichisit, addr, code, alloc_type_name[code],
145bc1f688bSRobert Mustacchi         mc_data_list_size);
146bc1f688bSRobert Mustacchi }
147bc1f688bSRobert Mustacchi #else
148bc1f688bSRobert Mustacchi #define  print_alloc_dealloc_detail(a,b,c)      /* nothing */
149bc1f688bSRobert Mustacchi #endif
150bc1f688bSRobert Mustacchi 
151bc1f688bSRobert Mustacchi /* Create a zeroed struct or die. */
152bc1f688bSRobert Mustacchi static void *
newone(void)153bc1f688bSRobert Mustacchi newone(void)
154bc1f688bSRobert Mustacchi {
155bc1f688bSRobert Mustacchi     struct mc_data_s *newd = malloc(sizeof(struct mc_data_s));
156bc1f688bSRobert Mustacchi 
157bc1f688bSRobert Mustacchi     if (newd == 0) {
158bc1f688bSRobert Mustacchi         fprintf(stderr, "out of memory , # %ld\n", mc_data_list_size);
159bc1f688bSRobert Mustacchi         exit(1);
160bc1f688bSRobert Mustacchi     }
161bc1f688bSRobert Mustacchi     memset(newd, 0, sizeof(struct mc_data_s));
162bc1f688bSRobert Mustacchi     return newd;
163bc1f688bSRobert Mustacchi }
164bc1f688bSRobert Mustacchi 
165bc1f688bSRobert Mustacchi /* Notify checker that get_alloc has allocated user data. */
166bc1f688bSRobert Mustacchi void
dwarf_malloc_check_alloc_data(void * addr_in,unsigned char code)167bc1f688bSRobert Mustacchi dwarf_malloc_check_alloc_data(void *addr_in, unsigned char code)
168bc1f688bSRobert Mustacchi {
169bc1f688bSRobert Mustacchi     struct mc_data_s *newd = newone();
170bc1f688bSRobert Mustacchi     unsigned long addr = (unsigned long) addr_in;
171bc1f688bSRobert Mustacchi     struct mc_data_s **base = &mc_data_hash[hash_address(addr)];
172bc1f688bSRobert Mustacchi 
173bc1f688bSRobert Mustacchi     print_alloc_dealloc_detail(addr, code, "alloc   ");
174bc1f688bSRobert Mustacchi     newd->mc_address = addr;
175bc1f688bSRobert Mustacchi     newd->mc_alloc_code = code;
176bc1f688bSRobert Mustacchi     newd->mc_type = MC_TYPE_ALLOC;
177bc1f688bSRobert Mustacchi     newd->mc_alloc_number = mc_data_list_size;
178bc1f688bSRobert Mustacchi     newd->mc_prev = *base;
179bc1f688bSRobert Mustacchi     *base = newd;
180bc1f688bSRobert Mustacchi     newd->mc_alloc_number = mc_data_list_size;
181bc1f688bSRobert Mustacchi     mc_data_list_size += 1;
182bc1f688bSRobert Mustacchi }
183bc1f688bSRobert Mustacchi 
184bc1f688bSRobert Mustacchi static void
print_entry(char * msg,struct mc_data_s * data)185bc1f688bSRobert Mustacchi print_entry(char *msg, struct mc_data_s *data)
186bc1f688bSRobert Mustacchi {
187bc1f688bSRobert Mustacchi     fprintf(stderr,
188bc1f688bSRobert Mustacchi         "%s: 0x%08lx code %2d (%s) type %s dealloc noted %u ct %u\n",
189bc1f688bSRobert Mustacchi         msg,
190bc1f688bSRobert Mustacchi         (long) data->mc_address,
191bc1f688bSRobert Mustacchi         data->mc_alloc_code,
192bc1f688bSRobert Mustacchi         alloc_type_name[data->mc_alloc_code],
193bc1f688bSRobert Mustacchi         (data->mc_type == MC_TYPE_ALLOC) ? "alloc  " :
194bc1f688bSRobert Mustacchi         (data->mc_type == MC_TYPE_DEALLOC) ? "dealloc" : "unknown",
195bc1f688bSRobert Mustacchi         (unsigned) data->mc_dealloc_noted,
196bc1f688bSRobert Mustacchi         (unsigned) data->mc_dealloc_noted_count);
197bc1f688bSRobert Mustacchi }
198bc1f688bSRobert Mustacchi 
199bc1f688bSRobert Mustacchi /* newd is a 'dealloc'.
200bc1f688bSRobert Mustacchi */
201bc1f688bSRobert Mustacchi static long
balanced_by_alloc_p(struct mc_data_s * newd,long * addr_match_num,struct mc_data_s ** addr_match,struct mc_data_s * base)202bc1f688bSRobert Mustacchi balanced_by_alloc_p(struct mc_data_s *newd,
203bc1f688bSRobert Mustacchi     long *addr_match_num,
204bc1f688bSRobert Mustacchi     struct mc_data_s **addr_match,
205bc1f688bSRobert Mustacchi     struct mc_data_s *base)
206bc1f688bSRobert Mustacchi {
207bc1f688bSRobert Mustacchi     struct mc_data_s *cur = base;
208bc1f688bSRobert Mustacchi 
209bc1f688bSRobert Mustacchi     for (; cur; cur = cur->mc_prev) {
210bc1f688bSRobert Mustacchi         if (cur->mc_address == newd->mc_address) {
211bc1f688bSRobert Mustacchi             if (cur->mc_type == MC_TYPE_ALLOC) {
212bc1f688bSRobert Mustacchi                 if (cur->mc_alloc_code == newd->mc_alloc_code) {
213bc1f688bSRobert Mustacchi                     *addr_match = cur;
214bc1f688bSRobert Mustacchi                     *addr_match_num = cur->mc_alloc_number;
215bc1f688bSRobert Mustacchi                     return cur->mc_alloc_number;
216bc1f688bSRobert Mustacchi                 } else {
217bc1f688bSRobert Mustacchi                     /* code mismatch */
218bc1f688bSRobert Mustacchi                     *addr_match = cur;
219bc1f688bSRobert Mustacchi                     *addr_match_num = cur->mc_alloc_number;
220bc1f688bSRobert Mustacchi                     return -1;
221bc1f688bSRobert Mustacchi                 }
222bc1f688bSRobert Mustacchi             } else {
223bc1f688bSRobert Mustacchi                 /* Unbalanced new/del */
224bc1f688bSRobert Mustacchi                 *addr_match = cur;
225bc1f688bSRobert Mustacchi                 *addr_match_num = cur->mc_alloc_number;
226bc1f688bSRobert Mustacchi                 return -1;
227bc1f688bSRobert Mustacchi             }
228bc1f688bSRobert Mustacchi         }
229bc1f688bSRobert Mustacchi     }
230bc1f688bSRobert Mustacchi     return -1;
231bc1f688bSRobert Mustacchi }
232bc1f688bSRobert Mustacchi 
233bc1f688bSRobert Mustacchi /*  A dealloc is to take place. Ensure it balances an alloc.
234bc1f688bSRobert Mustacchi */
235bc1f688bSRobert Mustacchi void
dwarf_malloc_check_dealloc_data(void * addr_in,unsigned char code)236bc1f688bSRobert Mustacchi dwarf_malloc_check_dealloc_data(void *addr_in, unsigned char code)
237bc1f688bSRobert Mustacchi {
238bc1f688bSRobert Mustacchi     struct mc_data_s *newd = newone();
239bc1f688bSRobert Mustacchi     long prev;
240bc1f688bSRobert Mustacchi     long addr_match_num = -1;
241bc1f688bSRobert Mustacchi     struct mc_data_s *addr_match = 0;
242bc1f688bSRobert Mustacchi     unsigned long addr = (unsigned long) addr_in;
243bc1f688bSRobert Mustacchi     struct mc_data_s **base = &mc_data_hash[hash_address(addr)];
244bc1f688bSRobert Mustacchi 
245bc1f688bSRobert Mustacchi 
246bc1f688bSRobert Mustacchi     print_alloc_dealloc_detail(addr, code, "dealloc ");
247bc1f688bSRobert Mustacchi     newd->mc_address = (unsigned long) addr;
248bc1f688bSRobert Mustacchi     newd->mc_alloc_code = code;
249bc1f688bSRobert Mustacchi     newd->mc_type = MC_TYPE_DEALLOC;
250bc1f688bSRobert Mustacchi     newd->mc_prev = *base;
251bc1f688bSRobert Mustacchi     prev =
252bc1f688bSRobert Mustacchi         balanced_by_alloc_p(newd, &addr_match_num, &addr_match, *base);
253bc1f688bSRobert Mustacchi     if (prev < 0) {
254bc1f688bSRobert Mustacchi         fprintf(stderr,
255bc1f688bSRobert Mustacchi             "Unbalanced dealloc at index %ld\n", mc_data_list_size);
256bc1f688bSRobert Mustacchi         print_entry("new", newd);
257bc1f688bSRobert Mustacchi         fprintf(stderr, "addr-match_num? %ld\n", addr_match_num);
258bc1f688bSRobert Mustacchi         if (addr_match) {
259bc1f688bSRobert Mustacchi             print_entry("prev entry", addr_match);
260bc1f688bSRobert Mustacchi             if (addr_match->mc_dealloc_noted > 1) {
261bc1f688bSRobert Mustacchi                 fprintf(stderr, "Above is Duplicate dealloc!\n");
262bc1f688bSRobert Mustacchi             }
263bc1f688bSRobert Mustacchi         }
264bc1f688bSRobert Mustacchi         abort();
265bc1f688bSRobert Mustacchi         exit(3);
266bc1f688bSRobert Mustacchi     }
267bc1f688bSRobert Mustacchi     addr_match->mc_dealloc_noted = 1;
268bc1f688bSRobert Mustacchi     addr_match->mc_dealloc_noted_count += 1;
269bc1f688bSRobert Mustacchi     if (addr_match->mc_dealloc_noted_count > 1) {
270bc1f688bSRobert Mustacchi         fprintf(stderr, "Double dealloc entry %ld\n", addr_match_num);
271bc1f688bSRobert Mustacchi         print_entry("new dealloc entry", newd);
272bc1f688bSRobert Mustacchi         print_entry("bad alloc entry", addr_match);
273bc1f688bSRobert Mustacchi     }
274bc1f688bSRobert Mustacchi     *base = newd;
275bc1f688bSRobert Mustacchi     mc_data_list_size += 1;
276bc1f688bSRobert Mustacchi }
277bc1f688bSRobert Mustacchi 
278bc1f688bSRobert Mustacchi /* Final check for leaks.
279bc1f688bSRobert Mustacchi */
280bc1f688bSRobert Mustacchi void
dwarf_malloc_check_complete(char * msg)281bc1f688bSRobert Mustacchi dwarf_malloc_check_complete(char *msg)
282bc1f688bSRobert Mustacchi {
283bc1f688bSRobert Mustacchi     long i = 0;
284bc1f688bSRobert Mustacchi     long total = mc_data_list_size;
285bc1f688bSRobert Mustacchi     long hash_slots_used = 0;
286bc1f688bSRobert Mustacchi     long max_chain_length = 0;
287bc1f688bSRobert Mustacchi 
288bc1f688bSRobert Mustacchi     fprintf(stderr, "Run complete, %s. %ld entries\n", msg, total);
289bc1f688bSRobert Mustacchi     for (; i < HASH_TABLE_SIZE; ++i) {
290bc1f688bSRobert Mustacchi         struct mc_data_s *cur = mc_data_hash[i];
291bc1f688bSRobert Mustacchi         long cur_chain_length = 0;
292bc1f688bSRobert Mustacchi 
293bc1f688bSRobert Mustacchi         if (cur == 0)
294bc1f688bSRobert Mustacchi             continue;
295bc1f688bSRobert Mustacchi         ++hash_slots_used;
296bc1f688bSRobert Mustacchi         for (; cur; cur = cur->mc_prev) {
297bc1f688bSRobert Mustacchi             ++cur_chain_length;
298bc1f688bSRobert Mustacchi             if (cur->mc_type == MC_TYPE_ALLOC) {
299bc1f688bSRobert Mustacchi                 if (cur->mc_dealloc_noted) {
300bc1f688bSRobert Mustacchi                     if (cur->mc_dealloc_noted > 1) {
301bc1f688bSRobert Mustacchi                         fprintf(stderr,
302bc1f688bSRobert Mustacchi                             " Duplicate dealloc! entry %ld\n",
303bc1f688bSRobert Mustacchi                             cur->mc_alloc_number);
304bc1f688bSRobert Mustacchi                         print_entry("duplicate dealloc", cur);
305bc1f688bSRobert Mustacchi 
306bc1f688bSRobert Mustacchi                     }
307bc1f688bSRobert Mustacchi                     continue;
308bc1f688bSRobert Mustacchi                 } else {
309bc1f688bSRobert Mustacchi                     fprintf(stderr, "malloc no dealloc, entry %ld\n",
310bc1f688bSRobert Mustacchi                         cur->mc_alloc_number);
311bc1f688bSRobert Mustacchi                     print_entry("dangle", cur);
312bc1f688bSRobert Mustacchi                 }
313bc1f688bSRobert Mustacchi             } else {
314bc1f688bSRobert Mustacchi                 /* mc_type is MC_TYPE_DEALLOC, already checked */
315bc1f688bSRobert Mustacchi 
316bc1f688bSRobert Mustacchi             }
317bc1f688bSRobert Mustacchi         }
318bc1f688bSRobert Mustacchi         if (cur_chain_length > max_chain_length) {
319bc1f688bSRobert Mustacchi             max_chain_length = cur_chain_length;
320bc1f688bSRobert Mustacchi         }
321bc1f688bSRobert Mustacchi     }
322bc1f688bSRobert Mustacchi     fprintf(stderr, "mc hash table slots=%ld, "
323bc1f688bSRobert Mustacchi         "used=%ld,  maxchain=%ld\n",
324bc1f688bSRobert Mustacchi         (long) HASH_TABLE_SIZE, hash_slots_used, max_chain_length);
325bc1f688bSRobert Mustacchi     return;
326bc1f688bSRobert Mustacchi }
327bc1f688bSRobert Mustacchi 
328bc1f688bSRobert Mustacchi #else
329bc1f688bSRobert Mustacchi 
330*4d9fdb46SRobert Mustacchi extern void *libdwarf_an_unused_function_so_not_empty_c_file(void);
331bc1f688bSRobert Mustacchi 
332bc1f688bSRobert Mustacchi #endif /* WANT_LIBBDWARF_MALLOC_CHECK */
333