1bc1f688Robert Mustacchi/*
2bc1f688Robert Mustacchi * This file and its contents are supplied under the terms of the
3bc1f688Robert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4bc1f688Robert Mustacchi * You may only use this file in accordance with the terms of version
5bc1f688Robert Mustacchi * 1.0 of the CDDL.
6bc1f688Robert Mustacchi *
7bc1f688Robert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8bc1f688Robert Mustacchi * source.  A copy of the CDDL is also available via the Internet at
9bc1f688Robert Mustacchi * http://www.illumos.org/license/CDDL.
10bc1f688Robert Mustacchi */
11bc1f688Robert Mustacchi
12bc1f688Robert Mustacchi/*
13fe2dc8bJohn Levon * Copyright 2020 Joyent, Inc.
14bc1f688Robert Mustacchi */
15bc1f688Robert Mustacchi
16bc1f688Robert Mustacchi/*
17bc1f688Robert Mustacchi * Dump information about CTF containers.
18bc1f688Robert Mustacchi */
19bc1f688Robert Mustacchi
20bc1f688Robert Mustacchi#include <stdio.h>
21bc1f688Robert Mustacchi#include <unistd.h>
22bc1f688Robert Mustacchi#include <libctf.h>
23bc1f688Robert Mustacchi#include <libgen.h>
24bc1f688Robert Mustacchi#include <stdarg.h>
25bc1f688Robert Mustacchi#include <stdlib.h>
26bc1f688Robert Mustacchi#include <stddef.h>
27bc1f688Robert Mustacchi#include <sys/sysmacros.h>
28bc1f688Robert Mustacchi#include <sys/types.h>
29bc1f688Robert Mustacchi#include <sys/stat.h>
30bc1f688Robert Mustacchi#include <sys/note.h>
31bc1f688Robert Mustacchi#include <fcntl.h>
32bc1f688Robert Mustacchi#include <errno.h>
33bc1f688Robert Mustacchi#include <string.h>
34bc1f688Robert Mustacchi#include <strings.h>
35bc1f688Robert Mustacchi#include <err.h>
36bc1f688Robert Mustacchi
37bc1f688Robert Mustacchi#define	MAX_NAMELEN (512)
38bc1f688Robert Mustacchi
39bc1f688Robert Mustacchitypedef enum ctfdump_arg {
40bc1f688Robert Mustacchi	CTFDUMP_OBJECTS =	0x001,
41bc1f688Robert Mustacchi	CTFDUMP_FUNCTIONS =	0x002,
42bc1f688Robert Mustacchi	CTFDUMP_HEADER =	0x004,
43bc1f688Robert Mustacchi	CTFDUMP_LABELS =	0x008,
44bc1f688Robert Mustacchi	CTFDUMP_STRINGS =	0x010,
45bc1f688Robert Mustacchi	CTFDUMP_STATS =		0x020,
46bc1f688Robert Mustacchi	CTFDUMP_TYPES =		0x040,
47bc1f688Robert Mustacchi	CTFDUMP_DEFAULT =	0x07f,
48bc1f688Robert Mustacchi	CTFDUMP_OUTPUT =	0x080,
49bc1f688Robert Mustacchi	CTFDUMP_SOURCE =	0x100,
50bc1f688Robert Mustacchi} ctfdump_arg_t;
51bc1f688Robert Mustacchi
52bc1f688Robert Mustacchitypedef struct ctfdump_stat {
53bc1f688Robert Mustacchi	ulong_t		cs_ndata;		/* number of data objects */
54bc1f688Robert Mustacchi	ulong_t		cs_nfuncs;		/* number of functions */
55bc1f688Robert Mustacchi	ulong_t		cs_nfuncargs;		/* number of function args */
56bc1f688Robert Mustacchi	ulong_t		cs_nfuncmax;		/* largest number of args */
57bc1f688Robert Mustacchi	ulong_t		cs_ntypes[CTF_K_MAX];	/* number of types */
58bc1f688Robert Mustacchi	ulong_t		cs_nsmembs;		/* number of struct members */
59bc1f688Robert Mustacchi	ulong_t		cs_nsmax;		/* largest number of members */
60bc1f688Robert Mustacchi	ulong_t		cs_structsz;		/* sum of structures sizes */
61bc1f688Robert Mustacchi	ulong_t		cs_sszmax;		/* largest structure */
62bc1f688Robert Mustacchi	ulong_t		cs_numembs;		/* number of union members */
63bc1f688Robert Mustacchi	ulong_t		cs_numax;		/* largest number of members */
64bc1f688Robert Mustacchi	ulong_t		cs_unionsz;		/* sum of unions sizes */
65bc1f688Robert Mustacchi	ulong_t		cs_uszmax;		/* largest union */
66bc1f688Robert Mustacchi	ulong_t		cs_nemembs;		/* number of enum members */
67bc1f688Robert Mustacchi	ulong_t		cs_nemax;		/* largest number of members */
68bc1f688Robert Mustacchi	ulong_t		cs_nstrings;		/* number of strings */
69bc1f688Robert Mustacchi	ulong_t		cs_strsz;		/* string size */
70bc1f688Robert Mustacchi	ulong_t		cs_strmax;		/* longest string */
71bc1f688Robert Mustacchi} ctfdump_stat_t;
72bc1f688Robert Mustacchi
73bc1f688Robert Mustacchitypedef struct {
74bc1f688Robert Mustacchi	char ci_name[MAX_NAMELEN];
75bc1f688Robert Mustacchi	ctf_id_t ci_id;
76bc1f688Robert Mustacchi	ulong_t ci_symidx;
77bc1f688Robert Mustacchi	ctf_funcinfo_t ci_funcinfo;
78bc1f688Robert Mustacchi} ctf_idname_t;
79bc1f688Robert Mustacchi
80bc1f688Robert Mustacchistatic ctf_idname_t *idnames;
81bc1f688Robert Mustacchistatic const char *g_progname;
82bc1f688Robert Mustacchistatic ctfdump_arg_t g_dump;
83bc1f688Robert Mustacchistatic ctf_file_t *g_fp;
84bc1f688Robert Mustacchistatic ctfdump_stat_t g_stats;
85bc1f688Robert Mustacchistatic ctf_id_t *g_fargc;
86bc1f688Robert Mustacchistatic int g_nfargc;
87bc1f688Robert Mustacchi
88bc1f688Robert Mustacchistatic int g_exit = 0;
89bc1f688Robert Mustacchi
90bc1f688Robert Mustacchistatic const char *ctfdump_fpenc[] = {
91bc1f688Robert Mustacchi	NULL,
92bc1f688Robert Mustacchi	"SINGLE",
93bc1f688Robert Mustacchi	"DOUBLE",
94bc1f688Robert Mustacchi	"COMPLEX",
95bc1f688Robert Mustacchi	"DCOMPLEX",
96bc1f688Robert Mustacchi	"LDCOMPLEX",
97bc1f688Robert Mustacchi	"LDOUBLE",
98bc1f688Robert Mustacchi	"INTERVAL",
99bc1f688Robert Mustacchi	"DINTERVAL",
100bc1f688Robert Mustacchi	"LDINTERVAL",
101bc1f688Robert Mustacchi	"IMAGINARY",
102bc1f688Robert Mustacchi	"DIMAGINARY",
103bc1f688Robert Mustacchi	"LDIMAGINARY"
104bc1f688Robert Mustacchi};
105bc1f688Robert Mustacchi
106bc1f688Robert Mustacchi/*
107bc1f688Robert Mustacchi * When stats are requested, we have to go through everything. To make our lives
108bc1f688Robert Mustacchi * easier, we'll just always allow the code to print everything out, but only
109bc1f688Robert Mustacchi * output it if we have actually enabled that section.
110bc1f688Robert Mustacchi */
111bc1f688Robert Mustacchistatic void
112bc1f688Robert Mustacchictfdump_printf(ctfdump_arg_t arg, const char *fmt, ...)
113bc1f688Robert Mustacchi{
114bc1f688Robert Mustacchi	va_list ap;
115bc1f688Robert Mustacchi
116bc1f688Robert Mustacchi	if ((arg & g_dump) == 0)
117bc1f688Robert Mustacchi		return;
118bc1f688Robert Mustacchi
119bc1f688Robert Mustacchi	va_start(ap, fmt);
120bc1f688Robert Mustacchi	(void) vfprintf(stdout, fmt, ap);
121bc1f688Robert Mustacchi	va_end(ap);
122bc1f688Robert Mustacchi}
123bc1f688Robert Mustacchi
124bc1f688Robert Mustacchistatic void
125bc1f688Robert Mustacchictfdump_fatal(const char *fmt, ...)
126bc1f688Robert Mustacchi{
127bc1f688Robert Mustacchi	va_list ap;
128bc1f688Robert Mustacchi
129bc1f688Robert Mustacchi	(void) fprintf(stderr, "%s: ", g_progname);
130bc1f688Robert Mustacchi	va_start(ap, fmt);
131bc1f688Robert Mustacchi	(void) vfprintf(stderr, fmt, ap);
132bc1f688Robert Mustacchi	va_end(ap);
133bc1f688Robert Mustacchi
134bc1f688Robert Mustacchi	exit(1);
135bc1f688Robert Mustacchi}
136bc1f688Robert Mustacchi
137bc1f688Robert Mustacchistatic void
138bc1f688Robert Mustacchictfdump_usage(const char *fmt, ...)
139bc1f688Robert Mustacchi{
140bc1f688Robert Mustacchi	if (fmt != NULL) {
141bc1f688Robert Mustacchi		va_list ap;
142bc1f688Robert Mustacchi		(void) fprintf(stderr, "%s: ", g_progname);
143bc1f688Robert Mustacchi		va_start(ap, fmt);
144bc1f688Robert Mustacchi		(void) vfprintf(stderr, fmt, ap);
145bc1f688Robert Mustacchi		va_end(ap);
146bc1f688Robert Mustacchi	}
147bc1f688Robert Mustacchi
148bc1f688Robert Mustacchi	(void) fprintf(stderr, "Usage: %s [-cdfhlsSt] [-p parent] [-u outfile] "
149bc1f688Robert Mustacchi	    "file\n"
150bc1f688Robert Mustacchi	    "\n"
151bc1f688Robert Mustacchi	    "\t-c  dump C-style output\n"
152bc1f688Robert Mustacchi	    "\t-d  dump object data\n"
153bc1f688Robert Mustacchi	    "\t-f  dump function data\n"
154bc1f688Robert Mustacchi	    "\t-h  dump the CTF header\n"
155bc1f688Robert Mustacchi	    "\t-l  dump the label table\n"
156bc1f688Robert Mustacchi	    "\t-p  use parent to supply additional information\n"
157bc1f688Robert Mustacchi	    "\t-s  dump the string table\n"
158bc1f688Robert Mustacchi	    "\t-S  dump statistics about the CTF container\n"
159bc1f688Robert Mustacchi	    "\t-t  dump type information\n"
160bc1f688Robert Mustacchi	    "\t-u  dump uncompressed CTF data to outfile\n",
161bc1f688Robert Mustacchi	    g_progname);
162bc1f688Robert Mustacchi}
163bc1f688Robert Mustacchi
164bc1f688Robert Mustacchistatic void
165bc1f688Robert Mustacchictfdump_title(ctfdump_arg_t arg, const char *header)
166bc1f688Robert Mustacchi{
167bc1f688Robert Mustacchi	static const char line[] = "----------------------------------------"
168bc1f688Robert Mustacchi	    "----------------------------------------";
169bc1f688Robert Mustacchi	ctfdump_printf(arg, "\n- %s %.*s\n\n", header, (int)78 - strlen(header),
170bc1f688Robert Mustacchi	    line);
171bc1f688Robert Mustacchi}
172bc1f688Robert Mustacchi
173bc1f688Robert Mustacchistatic int
174bc1f688Robert Mustacchictfdump_objects_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg)
175bc1f688Robert Mustacchi{
176bc1f688Robert Mustacchi	_NOTE(ARGUNUSED(arg));
177bc1f688Robert Mustacchi
178bc1f688Robert Mustacchi	int len;
179bc1f688Robert Mustacchi
180bc1f688Robert Mustacchi	len = snprintf(NULL, 0, "  [%lu] %ld", g_stats.cs_ndata, id);
181bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_OBJECTS, "  [%lu] %ld %*s%s (%lu)\n",
182bc1f688Robert Mustacchi	    g_stats.cs_ndata, id, MAX(15 - len, 0), "", name, symidx);
183bc1f688Robert Mustacchi	g_stats.cs_ndata++;
184bc1f688Robert Mustacchi	return (0);
185bc1f688Robert Mustacchi}
186bc1f688Robert Mustacchi
187bc1f688Robert Mustacchistatic void
188bc1f688Robert Mustacchictfdump_objects(void)
189bc1f688Robert Mustacchi{
190bc1f688Robert Mustacchi	ctfdump_title(CTFDUMP_OBJECTS, "Data Objects");
191bc1f688Robert Mustacchi	if (ctf_object_iter(g_fp, ctfdump_objects_cb, NULL) == CTF_ERR) {
192bc1f688Robert Mustacchi		warnx("failed to dump objects: %s",
193bc1f688Robert Mustacchi		    ctf_errmsg(ctf_errno(g_fp)));
194bc1f688Robert Mustacchi		g_exit = 1;
195bc1f688Robert Mustacchi	}
196bc1f688Robert Mustacchi}
197bc1f688Robert Mustacchi
198bc1f688Robert Mustacchistatic void
199bc1f688Robert Mustacchictfdump_fargs_grow(int nargs)
200bc1f688Robert Mustacchi{
201bc1f688Robert Mustacchi	if (g_nfargc < nargs) {
202bc1f688Robert Mustacchi		g_fargc = realloc(g_fargc, sizeof (ctf_id_t) * nargs);
203bc1f688Robert Mustacchi		if (g_fargc == NULL)
204bc1f688Robert Mustacchi			ctfdump_fatal("failed to get memory for %d "
205bc1f688Robert Mustacchi			    "ctf_id_t's\n", nargs);
206bc1f688Robert Mustacchi		g_nfargc = nargs;
207bc1f688Robert Mustacchi	}
208bc1f688Robert Mustacchi}
209bc1f688Robert Mustacchi
210bc1f688Robert Mustacchistatic int
211bc1f688Robert Mustacchictfdump_functions_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *ctc,
212bc1f688Robert Mustacchi    void *arg)
213bc1f688Robert Mustacchi{
214bc1f688Robert Mustacchi	_NOTE(ARGUNUSED(arg));
215bc1f688Robert Mustacchi	int i;
216bc1f688Robert Mustacchi
217bc1f688Robert Mustacchi	if (ctc->ctc_argc != 0) {
218bc1f688Robert Mustacchi		ctfdump_fargs_grow(ctc->ctc_argc);
219bc1f688Robert Mustacchi		if (ctf_func_args(g_fp, symidx, g_nfargc, g_fargc) == CTF_ERR)
220bc1f688Robert Mustacchi			ctfdump_fatal("failed to get arguments for function "
221bc1f688Robert Mustacchi			    "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
222bc1f688Robert Mustacchi	}
223bc1f688Robert Mustacchi
224bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_FUNCTIONS,
225bc1f688Robert Mustacchi	    "  [%lu] %s (%lu) returns: %ld args: (", g_stats.cs_nfuncs, name,
226bc1f688Robert Mustacchi	    symidx, ctc->ctc_return);
227bc1f688Robert Mustacchi	for (i = 0; i < ctc->ctc_argc; i++)
228bc1f688Robert Mustacchi		ctfdump_printf(CTFDUMP_FUNCTIONS, "%ld%s", g_fargc[i],
229bc1f688Robert Mustacchi		    i + 1 == ctc->ctc_argc ? "" : ", ");
230bc1f688Robert Mustacchi	if (ctc->ctc_flags & CTF_FUNC_VARARG)
231bc1f688Robert Mustacchi		ctfdump_printf(CTFDUMP_FUNCTIONS, "%s...",
232bc1f688Robert Mustacchi		    ctc->ctc_argc == 0 ? "" : ", ");
233bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_FUNCTIONS, ")\n");
234bc1f688Robert Mustacchi
235bc1f688Robert Mustacchi	g_stats.cs_nfuncs++;
236bc1f688Robert Mustacchi	g_stats.cs_nfuncargs += ctc->ctc_argc;
237bc1f688Robert Mustacchi	g_stats.cs_nfuncmax = MAX(ctc->ctc_argc, g_stats.cs_nfuncmax);
238bc1f688Robert Mustacchi
239bc1f688Robert Mustacchi	return (0);
240bc1f688Robert Mustacchi}
241bc1f688Robert Mustacchi
242bc1f688Robert Mustacchistatic void
243bc1f688Robert Mustacchictfdump_functions(void)
244bc1f688Robert Mustacchi{
245bc1f688Robert Mustacchi	ctfdump_title(CTFDUMP_FUNCTIONS, "Functions");
246bc1f688Robert Mustacchi
247bc1f688Robert Mustacchi	if (ctf_function_iter(g_fp, ctfdump_functions_cb, NULL) == CTF_ERR) {
248bc1f688Robert Mustacchi		warnx("failed to dump functions: %s",
249bc1f688Robert Mustacchi		    ctf_errmsg(ctf_errno(g_fp)));
250bc1f688Robert Mustacchi		g_exit = 1;
251bc1f688Robert Mustacchi	}
252bc1f688Robert Mustacchi}
253bc1f688Robert Mustacchi
254bc1f688Robert Mustacchistatic void
255bc1f688Robert Mustacchictfdump_header(void)
256bc1f688Robert Mustacchi{
257bc1f688Robert Mustacchi	const ctf_header_t *hp;
258bc1f688Robert Mustacchi	const char *parname, *parlabel;
259bc1f688Robert Mustacchi
260bc1f688Robert Mustacchi	ctfdump_title(CTFDUMP_HEADER, "CTF Header");
261bc1f688Robert Mustacchi	ctf_dataptr(g_fp, (const void **)&hp, NULL);
262bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_magic    = 0x%04x\n",
263bc1f688Robert Mustacchi	    hp->cth_magic);
264bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_version  = %u\n",
265bc1f688Robert Mustacchi	    hp->cth_version);
266bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_flags    = 0x%02x\n",
267bc1f688Robert Mustacchi	    ctf_flags(g_fp));
268bc1f688Robert Mustacchi	parname = ctf_parent_name(g_fp);
269bc1f688Robert Mustacchi	parlabel = ctf_parent_label(g_fp);
270bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_parlabel = %s\n",
271bc1f688Robert Mustacchi	    parlabel == NULL ? "(anon)" : parlabel);
272bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_parname  = %s\n",
273bc1f688Robert Mustacchi	    parname == NULL ? "(anon)" : parname);
274bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_lbloff   = %u\n",
275bc1f688Robert Mustacchi	    hp->cth_lbloff);
276bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_objtoff  = %u\n",
277bc1f688Robert Mustacchi	    hp->cth_objtoff);
278bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_funcoff  = %u\n",
279bc1f688Robert Mustacchi	    hp->cth_funcoff);
280bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_typeoff  = %u\n",
281bc1f688Robert Mustacchi	    hp->cth_typeoff);
282bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_stroff   = %u\n",
283bc1f688Robert Mustacchi	    hp->cth_stroff);
284bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_HEADER, "  cth_strlen   = %u\n",
285bc1f688Robert Mustacchi	    hp->cth_strlen);
286bc1f688Robert Mustacchi}
287bc1f688Robert Mustacchi
288bc1f688Robert Mustacchistatic int
289bc1f688Robert Mustacchictfdump_labels_cb(const char *name, const ctf_lblinfo_t *li, void *arg)
290bc1f688Robert Mustacchi{
291bc1f688Robert Mustacchi	_NOTE(ARGUNUSED(arg));
292bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_LABELS, "  %5ld %s\n", li->ctb_typeidx, name);
293bc1f688Robert Mustacchi	return (0);
294bc1f688Robert Mustacchi}
295bc1f688Robert Mustacchi
296bc1f688Robert Mustacchistatic void
297bc1f688Robert Mustacchictfdump_labels(void)
298bc1f688Robert Mustacchi{
299bc1f688Robert Mustacchi	ctfdump_title(CTFDUMP_LABELS, "Label Table");
300bc1f688Robert Mustacchi	if (ctf_label_iter(g_fp, ctfdump_labels_cb, NULL) == CTF_ERR) {
301bc1f688Robert Mustacchi		warnx("failed to dump labels: %s",
302bc1f688Robert Mustacchi		    ctf_errmsg(ctf_errno(g_fp)));
303bc1f688Robert Mustacchi		g_exit = 1;
304bc1f688Robert Mustacchi	}
305bc1f688Robert Mustacchi}
306bc1f688Robert Mustacchi
307bc1f688Robert Mustacchistatic int
308bc1f688Robert Mustacchictfdump_strings_cb(const char *s, void *arg)
309bc1f688Robert Mustacchi{
310bc1f688Robert Mustacchi	size_t len = strlen(s) + 1;
311bc1f688Robert Mustacchi	ulong_t *stroff = arg;
312bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_STRINGS, "  [%lu] %s\n", *stroff,
313bc1f688Robert Mustacchi	    *s == '\0' ? "\\0" : s);
314bc1f688Robert Mustacchi	*stroff = *stroff + len;
315bc1f688Robert Mustacchi	g_stats.cs_nstrings++;
316bc1f688Robert Mustacchi	g_stats.cs_strsz += len;
317bc1f688Robert Mustacchi	g_stats.cs_strmax = MAX(g_stats.cs_strmax, len);
318bc1f688Robert Mustacchi	return (0);
319bc1f688Robert Mustacchi}
320bc1f688Robert Mustacchi
321bc1f688Robert Mustacchistatic void
322bc1f688Robert Mustacchictfdump_strings(void)
323bc1f688Robert Mustacchi{
324bc1f688Robert Mustacchi	ulong_t stroff = 0;
325bc1f688Robert Mustacchi
326bc1f688Robert Mustacchi	ctfdump_title(CTFDUMP_STRINGS, "String Table");
327bc1f688Robert Mustacchi	if (ctf_string_iter(g_fp, ctfdump_strings_cb, &stroff) == CTF_ERR) {
328bc1f688Robert Mustacchi		warnx("failed to dump strings: %s",
329bc1f688Robert Mustacchi		    ctf_errmsg(ctf_errno(g_fp)));
330bc1f688Robert Mustacchi		g_exit = 1;
331bc1f688Robert Mustacchi	}
332bc1f688Robert Mustacchi}
333bc1f688Robert Mustacchi
334bc1f688Robert Mustacchistatic void
335bc1f688Robert Mustacchictfdump_stat_int(const char *name, ulong_t value)
336bc1f688Robert Mustacchi{
337bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_STATS, "  %-36s= %lu\n", name, value);
338bc1f688Robert Mustacchi}
339bc1f688Robert Mustacchi
340bc1f688Robert Mustacchistatic void
341bc1f688Robert Mustacchictfdump_stat_fp(const char *name, float value)
342bc1f688Robert Mustacchi{
343bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_STATS, "  %-36s= %.2f\n", name, value);
344bc1f688Robert Mustacchi}
345bc1f688Robert Mustacchi
346bc1f688Robert Mustacchistatic void
347bc1f688Robert Mustacchictfdump_stats(void)
348bc1f688Robert Mustacchi{
349bc1f688Robert Mustacchi	int i;
350bc1f688Robert Mustacchi	ulong_t sum;
351bc1f688Robert Mustacchi
352bc1f688Robert Mustacchi	ctfdump_title(CTFDUMP_STATS, "CTF Statistics");
353bc1f688Robert Mustacchi
354bc1f688Robert Mustacchi	ctfdump_stat_int("total number of data objects", g_stats.cs_ndata);
355bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_STATS, "\n");
356bc1f688Robert Mustacchi	ctfdump_stat_int("total number of functions", g_stats.cs_nfuncs);
357bc1f688Robert Mustacchi	ctfdump_stat_int("total number of function arguments",
358bc1f688Robert Mustacchi	    g_stats.cs_nfuncargs);
359bc1f688Robert Mustacchi	ctfdump_stat_int("maximum argument list length", g_stats.cs_nfuncmax);
360bc1f688Robert Mustacchi	if (g_stats.cs_nfuncs != 0)
361bc1f688Robert Mustacchi		ctfdump_stat_fp("average argument list length",
362bc1f688Robert Mustacchi		    (float)g_stats.cs_nfuncargs / (float)g_stats.cs_nfuncs);
363bc1f688Robert Mustacchi	ctfdump_printf(CTFDUMP_STATS, "\n");
364bc1f688Robert Mustacchi
365bc1f688Robert Mustacchi	sum = 0;
366bc1f688Robert Mustacchi	for (i = 0; i < CTF_K_MAX; i++)
367bc1f688Robert Mustacchi		sum += g_stats.cs_ntypes[i];
368bc1f688Robert Mustacchi	ctfdump_stat_int("total number of types", sum);
369bc1f688Robert Mustacchi	ctfdump_stat_int("total number of integers",
370bc1f688Robert Mustacchi	    g_stats.cs_ntypes[CTF_K_INTEGER]);
371bc1f688Robert Mustacchi	ctfdump_stat_int("total number of floats",
372bc1f688Robert Mustacchi	    g_stats.cs_ntypes[CTF_K_FLOAT]);
373bc1f688Robert Mustacchi	ctfdump_stat_int("total number of pointers",
374bc1f688Robert Mustacchi	    g_stats.cs_ntypes[CTF_K_POINTER]);
375bc1f688Robert Mustacchi	ctfdump_stat_int("total number of arrays",
376bc1f688Robert Mustacchi	    g_stats.cs_ntypes[CTF_K_ARRAY]);
377bc1f688Robert Mustacchi	ctfdump_stat_int("total number of func types",
378