xref: /titanic_52/usr/src/cmd/ctfdump/ctfdump.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
1*7fd79137SRobert Mustacchi /*
2*7fd79137SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*7fd79137SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*7fd79137SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*7fd79137SRobert Mustacchi  * 1.0 of the CDDL.
6*7fd79137SRobert Mustacchi  *
7*7fd79137SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*7fd79137SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*7fd79137SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*7fd79137SRobert Mustacchi  */
11*7fd79137SRobert Mustacchi 
12*7fd79137SRobert Mustacchi /*
13*7fd79137SRobert Mustacchi  * Copyright (c) 2018, Joyent, Inc.
14*7fd79137SRobert Mustacchi  */
15*7fd79137SRobert Mustacchi 
16*7fd79137SRobert Mustacchi /*
17*7fd79137SRobert Mustacchi  * Dump information about CTF containers.
18*7fd79137SRobert Mustacchi  */
19*7fd79137SRobert Mustacchi 
20*7fd79137SRobert Mustacchi #include <stdio.h>
21*7fd79137SRobert Mustacchi #include <unistd.h>
22*7fd79137SRobert Mustacchi #include <libctf.h>
23*7fd79137SRobert Mustacchi #include <libgen.h>
24*7fd79137SRobert Mustacchi #include <stdarg.h>
25*7fd79137SRobert Mustacchi #include <stdlib.h>
26*7fd79137SRobert Mustacchi #include <stddef.h>
27*7fd79137SRobert Mustacchi #include <sys/sysmacros.h>
28*7fd79137SRobert Mustacchi #include <sys/types.h>
29*7fd79137SRobert Mustacchi #include <sys/stat.h>
30*7fd79137SRobert Mustacchi #include <sys/note.h>
31*7fd79137SRobert Mustacchi #include <fcntl.h>
32*7fd79137SRobert Mustacchi #include <errno.h>
33*7fd79137SRobert Mustacchi #include <string.h>
34*7fd79137SRobert Mustacchi #include <strings.h>
35*7fd79137SRobert Mustacchi #include <err.h>
36*7fd79137SRobert Mustacchi 
37*7fd79137SRobert Mustacchi #define	MAX_NAMELEN (512)
38*7fd79137SRobert Mustacchi 
39*7fd79137SRobert Mustacchi typedef enum ctfdump_arg {
40*7fd79137SRobert Mustacchi 	CTFDUMP_OBJECTS =	0x001,
41*7fd79137SRobert Mustacchi 	CTFDUMP_FUNCTIONS =	0x002,
42*7fd79137SRobert Mustacchi 	CTFDUMP_HEADER =	0x004,
43*7fd79137SRobert Mustacchi 	CTFDUMP_LABELS =	0x008,
44*7fd79137SRobert Mustacchi 	CTFDUMP_STRINGS =	0x010,
45*7fd79137SRobert Mustacchi 	CTFDUMP_STATS =		0x020,
46*7fd79137SRobert Mustacchi 	CTFDUMP_TYPES =		0x040,
47*7fd79137SRobert Mustacchi 	CTFDUMP_DEFAULT =	0x07f,
48*7fd79137SRobert Mustacchi 	CTFDUMP_OUTPUT =	0x080,
49*7fd79137SRobert Mustacchi 	CTFDUMP_SOURCE =	0x100,
50*7fd79137SRobert Mustacchi } ctfdump_arg_t;
51*7fd79137SRobert Mustacchi 
52*7fd79137SRobert Mustacchi typedef struct ctfdump_stat {
53*7fd79137SRobert Mustacchi 	ulong_t		cs_ndata;		/* number of data objects */
54*7fd79137SRobert Mustacchi 	ulong_t		cs_nfuncs;		/* number of functions */
55*7fd79137SRobert Mustacchi 	ulong_t		cs_nfuncargs;		/* number of function args */
56*7fd79137SRobert Mustacchi 	ulong_t		cs_nfuncmax;		/* largest number of args */
57*7fd79137SRobert Mustacchi 	ulong_t		cs_ntypes[CTF_K_MAX];	/* number of types */
58*7fd79137SRobert Mustacchi 	ulong_t		cs_nsmembs;		/* number of struct members */
59*7fd79137SRobert Mustacchi 	ulong_t		cs_nsmax;		/* largest number of members */
60*7fd79137SRobert Mustacchi 	ulong_t		cs_structsz;		/* sum of structures sizes */
61*7fd79137SRobert Mustacchi 	ulong_t		cs_sszmax;		/* largest structure */
62*7fd79137SRobert Mustacchi 	ulong_t		cs_numembs;		/* number of union members */
63*7fd79137SRobert Mustacchi 	ulong_t		cs_numax;		/* largest number of members */
64*7fd79137SRobert Mustacchi 	ulong_t		cs_unionsz;		/* sum of unions sizes */
65*7fd79137SRobert Mustacchi 	ulong_t		cs_uszmax;		/* largest union */
66*7fd79137SRobert Mustacchi 	ulong_t		cs_nemembs;		/* number of enum members */
67*7fd79137SRobert Mustacchi 	ulong_t		cs_nemax;		/* largest number of members */
68*7fd79137SRobert Mustacchi 	ulong_t		cs_nstrings;		/* number of strings */
69*7fd79137SRobert Mustacchi 	ulong_t		cs_strsz;		/* string size */
70*7fd79137SRobert Mustacchi 	ulong_t		cs_strmax;		/* longest string */
71*7fd79137SRobert Mustacchi } ctfdump_stat_t;
72*7fd79137SRobert Mustacchi 
73*7fd79137SRobert Mustacchi typedef struct {
74*7fd79137SRobert Mustacchi 	char ci_name[MAX_NAMELEN];
75*7fd79137SRobert Mustacchi 	ctf_id_t ci_id;
76*7fd79137SRobert Mustacchi 	ulong_t ci_symidx;
77*7fd79137SRobert Mustacchi 	ctf_funcinfo_t ci_funcinfo;
78*7fd79137SRobert Mustacchi } ctf_idname_t;
79*7fd79137SRobert Mustacchi 
80*7fd79137SRobert Mustacchi static ctf_idname_t *idnames;
81*7fd79137SRobert Mustacchi static const char *g_progname;
82*7fd79137SRobert Mustacchi static ctfdump_arg_t g_dump;
83*7fd79137SRobert Mustacchi static ctf_file_t *g_fp;
84*7fd79137SRobert Mustacchi static ctfdump_stat_t g_stats;
85*7fd79137SRobert Mustacchi static ctf_id_t *g_fargc;
86*7fd79137SRobert Mustacchi static int g_nfargc;
87*7fd79137SRobert Mustacchi 
88*7fd79137SRobert Mustacchi static int g_exit = 0;
89*7fd79137SRobert Mustacchi 
90*7fd79137SRobert Mustacchi static const char *ctfdump_fpenc[] = {
91*7fd79137SRobert Mustacchi 	NULL,
92*7fd79137SRobert Mustacchi 	"SINGLE",
93*7fd79137SRobert Mustacchi 	"DOUBLE",
94*7fd79137SRobert Mustacchi 	"COMPLEX",
95*7fd79137SRobert Mustacchi 	"DCOMPLEX",
96*7fd79137SRobert Mustacchi 	"LDCOMPLEX",
97*7fd79137SRobert Mustacchi 	"LDOUBLE",
98*7fd79137SRobert Mustacchi 	"INTERVAL",
99*7fd79137SRobert Mustacchi 	"DINTERVAL",
100*7fd79137SRobert Mustacchi 	"LDINTERVAL",
101*7fd79137SRobert Mustacchi 	"IMAGINARY",
102*7fd79137SRobert Mustacchi 	"DIMAGINARY",
103*7fd79137SRobert Mustacchi 	"LDIMAGINARY"
104*7fd79137SRobert Mustacchi };
105*7fd79137SRobert Mustacchi 
106*7fd79137SRobert Mustacchi /*
107*7fd79137SRobert Mustacchi  * When stats are requested, we have to go through everything. To make our lives
108*7fd79137SRobert Mustacchi  * easier, we'll just always allow the code to print everything out, but only
109*7fd79137SRobert Mustacchi  * output it if we have actually enabled that section.
110*7fd79137SRobert Mustacchi  */
111*7fd79137SRobert Mustacchi static void
112*7fd79137SRobert Mustacchi ctfdump_printf(ctfdump_arg_t arg, const char *fmt, ...)
113*7fd79137SRobert Mustacchi {
114*7fd79137SRobert Mustacchi 	va_list ap;
115*7fd79137SRobert Mustacchi 
116*7fd79137SRobert Mustacchi 	if ((arg & g_dump) == 0)
117*7fd79137SRobert Mustacchi 		return;
118*7fd79137SRobert Mustacchi 
119*7fd79137SRobert Mustacchi 	va_start(ap, fmt);
120*7fd79137SRobert Mustacchi 	(void) vfprintf(stdout, fmt, ap);
121*7fd79137SRobert Mustacchi 	va_end(ap);
122*7fd79137SRobert Mustacchi }
123*7fd79137SRobert Mustacchi 
124*7fd79137SRobert Mustacchi static void
125*7fd79137SRobert Mustacchi ctfdump_fatal(const char *fmt, ...)
126*7fd79137SRobert Mustacchi {
127*7fd79137SRobert Mustacchi 	va_list ap;
128*7fd79137SRobert Mustacchi 
129*7fd79137SRobert Mustacchi 	(void) fprintf(stderr, "%s: ", g_progname);
130*7fd79137SRobert Mustacchi 	va_start(ap, fmt);
131*7fd79137SRobert Mustacchi 	(void) vfprintf(stderr, fmt, ap);
132*7fd79137SRobert Mustacchi 	va_end(ap);
133*7fd79137SRobert Mustacchi 
134*7fd79137SRobert Mustacchi 	exit(1);
135*7fd79137SRobert Mustacchi }
136*7fd79137SRobert Mustacchi 
137*7fd79137SRobert Mustacchi static void
138*7fd79137SRobert Mustacchi ctfdump_usage(const char *fmt, ...)
139*7fd79137SRobert Mustacchi {
140*7fd79137SRobert Mustacchi 	if (fmt != NULL) {
141*7fd79137SRobert Mustacchi 		va_list ap;
142*7fd79137SRobert Mustacchi 		(void) fprintf(stderr, "%s: ", g_progname);
143*7fd79137SRobert Mustacchi 		va_start(ap, fmt);
144*7fd79137SRobert Mustacchi 		(void) vfprintf(stderr, fmt, ap);
145*7fd79137SRobert Mustacchi 		va_end(ap);
146*7fd79137SRobert Mustacchi 	}
147*7fd79137SRobert Mustacchi 
148*7fd79137SRobert Mustacchi 	(void) fprintf(stderr, "Usage: %s [-cdfhlsSt] [-p parent] [-u outfile] "
149*7fd79137SRobert Mustacchi 	    "file\n"
150*7fd79137SRobert Mustacchi 	    "\n"
151*7fd79137SRobert Mustacchi 	    "\t-c  dump C-style output\n"
152*7fd79137SRobert Mustacchi 	    "\t-d  dump object data\n"
153*7fd79137SRobert Mustacchi 	    "\t-f  dump function data\n"
154*7fd79137SRobert Mustacchi 	    "\t-h  dump the CTF header\n"
155*7fd79137SRobert Mustacchi 	    "\t-l  dump the label table\n"
156*7fd79137SRobert Mustacchi 	    "\t-p  use parent to supply additional information\n"
157*7fd79137SRobert Mustacchi 	    "\t-s  dump the string table\n"
158*7fd79137SRobert Mustacchi 	    "\t-S  dump statistics about the CTF container\n"
159*7fd79137SRobert Mustacchi 	    "\t-t  dump type information\n"
160*7fd79137SRobert Mustacchi 	    "\t-u  dump uncompressed CTF data to outfile\n",
161*7fd79137SRobert Mustacchi 	    g_progname);
162*7fd79137SRobert Mustacchi }
163*7fd79137SRobert Mustacchi 
164*7fd79137SRobert Mustacchi static void
165*7fd79137SRobert Mustacchi ctfdump_title(ctfdump_arg_t arg, const char *header)
166*7fd79137SRobert Mustacchi {
167*7fd79137SRobert Mustacchi 	static const char line[] = "----------------------------------------"
168*7fd79137SRobert Mustacchi 	    "----------------------------------------";
169*7fd79137SRobert Mustacchi 	ctfdump_printf(arg, "\n- %s %.*s\n\n", header, (int)78 - strlen(header),
170*7fd79137SRobert Mustacchi 	    line);
171*7fd79137SRobert Mustacchi }
172*7fd79137SRobert Mustacchi 
173*7fd79137SRobert Mustacchi static int
174*7fd79137SRobert Mustacchi ctfdump_objects_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg)
175*7fd79137SRobert Mustacchi {
176*7fd79137SRobert Mustacchi 	_NOTE(ARGUNUSED(arg));
177*7fd79137SRobert Mustacchi 
178*7fd79137SRobert Mustacchi 	int len;
179*7fd79137SRobert Mustacchi 
180*7fd79137SRobert Mustacchi 	len = snprintf(NULL, 0, "  [%lu] %ld", g_stats.cs_ndata, id);
181*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_OBJECTS, "  [%lu] %ld %*s%s (%lu)\n",
182*7fd79137SRobert Mustacchi 	    g_stats.cs_ndata, id, MAX(15 - len, 0), "", name, symidx);
183*7fd79137SRobert Mustacchi 	g_stats.cs_ndata++;
184*7fd79137SRobert Mustacchi 	return (0);
185*7fd79137SRobert Mustacchi }
186*7fd79137SRobert Mustacchi 
187*7fd79137SRobert Mustacchi static void
188*7fd79137SRobert Mustacchi ctfdump_objects(void)
189*7fd79137SRobert Mustacchi {
190*7fd79137SRobert Mustacchi 	ctfdump_title(CTFDUMP_OBJECTS, "Data Objects");
191*7fd79137SRobert Mustacchi 	if (ctf_object_iter(g_fp, ctfdump_objects_cb, NULL) == CTF_ERR) {
192*7fd79137SRobert Mustacchi 		warnx("failed to dump objects: %s",
193*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
194*7fd79137SRobert Mustacchi 		g_exit = 1;
195*7fd79137SRobert Mustacchi 	}
196*7fd79137SRobert Mustacchi }
197*7fd79137SRobert Mustacchi 
198*7fd79137SRobert Mustacchi static void
199*7fd79137SRobert Mustacchi ctfdump_fargs_grow(int nargs)
200*7fd79137SRobert Mustacchi {
201*7fd79137SRobert Mustacchi 	if (g_nfargc < nargs) {
202*7fd79137SRobert Mustacchi 		g_fargc = realloc(g_fargc, sizeof (ctf_id_t) * nargs);
203*7fd79137SRobert Mustacchi 		if (g_fargc == NULL)
204*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get memory for %d "
205*7fd79137SRobert Mustacchi 			    "ctf_id_t's\n", nargs);
206*7fd79137SRobert Mustacchi 		g_nfargc = nargs;
207*7fd79137SRobert Mustacchi 	}
208*7fd79137SRobert Mustacchi }
209*7fd79137SRobert Mustacchi 
210*7fd79137SRobert Mustacchi static int
211*7fd79137SRobert Mustacchi ctfdump_functions_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *ctc,
212*7fd79137SRobert Mustacchi     void *arg)
213*7fd79137SRobert Mustacchi {
214*7fd79137SRobert Mustacchi 	_NOTE(ARGUNUSED(arg));
215*7fd79137SRobert Mustacchi 	int i;
216*7fd79137SRobert Mustacchi 
217*7fd79137SRobert Mustacchi 	if (ctc->ctc_argc != 0) {
218*7fd79137SRobert Mustacchi 		ctfdump_fargs_grow(ctc->ctc_argc);
219*7fd79137SRobert Mustacchi 		if (ctf_func_args(g_fp, symidx, g_nfargc, g_fargc) == CTF_ERR)
220*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get arguments for function "
221*7fd79137SRobert Mustacchi 			    "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
222*7fd79137SRobert Mustacchi 	}
223*7fd79137SRobert Mustacchi 
224*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_FUNCTIONS,
225*7fd79137SRobert Mustacchi 	    "  [%lu] %s (%lu) returns: %ld args: (", g_stats.cs_nfuncs, name,
226*7fd79137SRobert Mustacchi 	    symidx, ctc->ctc_return);
227*7fd79137SRobert Mustacchi 	for (i = 0; i < ctc->ctc_argc; i++)
228*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_FUNCTIONS, "%ld%s", g_fargc[i],
229*7fd79137SRobert Mustacchi 		    i + 1 == ctc->ctc_argc ? "" : ", ");
230*7fd79137SRobert Mustacchi 	if (ctc->ctc_flags & CTF_FUNC_VARARG)
231*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_FUNCTIONS, "%s...",
232*7fd79137SRobert Mustacchi 		    ctc->ctc_argc == 0 ? "" : ", ");
233*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_FUNCTIONS, ")\n");
234*7fd79137SRobert Mustacchi 
235*7fd79137SRobert Mustacchi 	g_stats.cs_nfuncs++;
236*7fd79137SRobert Mustacchi 	g_stats.cs_nfuncargs += ctc->ctc_argc;
237*7fd79137SRobert Mustacchi 	g_stats.cs_nfuncmax = MAX(ctc->ctc_argc, g_stats.cs_nfuncmax);
238*7fd79137SRobert Mustacchi 
239*7fd79137SRobert Mustacchi 	return (0);
240*7fd79137SRobert Mustacchi }
241*7fd79137SRobert Mustacchi 
242*7fd79137SRobert Mustacchi static void
243*7fd79137SRobert Mustacchi ctfdump_functions(void)
244*7fd79137SRobert Mustacchi {
245*7fd79137SRobert Mustacchi 	ctfdump_title(CTFDUMP_FUNCTIONS, "Functions");
246*7fd79137SRobert Mustacchi 
247*7fd79137SRobert Mustacchi 	if (ctf_function_iter(g_fp, ctfdump_functions_cb, NULL) == CTF_ERR) {
248*7fd79137SRobert Mustacchi 		warnx("failed to dump functions: %s",
249*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
250*7fd79137SRobert Mustacchi 		g_exit = 1;
251*7fd79137SRobert Mustacchi 	}
252*7fd79137SRobert Mustacchi }
253*7fd79137SRobert Mustacchi 
254*7fd79137SRobert Mustacchi static void
255*7fd79137SRobert Mustacchi ctfdump_header(void)
256*7fd79137SRobert Mustacchi {
257*7fd79137SRobert Mustacchi 	const ctf_header_t *hp;
258*7fd79137SRobert Mustacchi 	const char *parname, *parlabel;
259*7fd79137SRobert Mustacchi 
260*7fd79137SRobert Mustacchi 	ctfdump_title(CTFDUMP_HEADER, "CTF Header");
261*7fd79137SRobert Mustacchi 	ctf_dataptr(g_fp, (const void **)&hp, NULL);
262*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_magic    = 0x%04x\n",
263*7fd79137SRobert Mustacchi 	    hp->cth_magic);
264*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_version  = %u\n",
265*7fd79137SRobert Mustacchi 	    hp->cth_version);
266*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_flags    = 0x%02x\n",
267*7fd79137SRobert Mustacchi 	    ctf_flags(g_fp));
268*7fd79137SRobert Mustacchi 	parname = ctf_parent_name(g_fp);
269*7fd79137SRobert Mustacchi 	parlabel = ctf_parent_label(g_fp);
270*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_parlabel = %s\n",
271*7fd79137SRobert Mustacchi 	    parlabel == NULL ? "(anon)" : parlabel);
272*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_parname  = %s\n",
273*7fd79137SRobert Mustacchi 	    parname == NULL ? "(anon)" : parname);
274*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_lbloff   = %u\n",
275*7fd79137SRobert Mustacchi 	    hp->cth_lbloff);
276*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_objtoff  = %u\n",
277*7fd79137SRobert Mustacchi 	    hp->cth_objtoff);
278*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_funcoff  = %u\n",
279*7fd79137SRobert Mustacchi 	    hp->cth_funcoff);
280*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_typeoff  = %u\n",
281*7fd79137SRobert Mustacchi 	    hp->cth_typeoff);
282*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_stroff   = %u\n",
283*7fd79137SRobert Mustacchi 	    hp->cth_stroff);
284*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_HEADER, "  cth_strlen   = %u\n",
285*7fd79137SRobert Mustacchi 	    hp->cth_strlen);
286*7fd79137SRobert Mustacchi }
287*7fd79137SRobert Mustacchi 
288*7fd79137SRobert Mustacchi static int
289*7fd79137SRobert Mustacchi ctfdump_labels_cb(const char *name, const ctf_lblinfo_t *li, void *arg)
290*7fd79137SRobert Mustacchi {
291*7fd79137SRobert Mustacchi 	_NOTE(ARGUNUSED(arg));
292*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_LABELS, "  %5ld %s\n", li->ctb_typeidx, name);
293*7fd79137SRobert Mustacchi 	return (0);
294*7fd79137SRobert Mustacchi }
295*7fd79137SRobert Mustacchi 
296*7fd79137SRobert Mustacchi static void
297*7fd79137SRobert Mustacchi ctfdump_labels(void)
298*7fd79137SRobert Mustacchi {
299*7fd79137SRobert Mustacchi 	ctfdump_title(CTFDUMP_LABELS, "Label Table");
300*7fd79137SRobert Mustacchi 	if (ctf_label_iter(g_fp, ctfdump_labels_cb, NULL) == CTF_ERR) {
301*7fd79137SRobert Mustacchi 		warnx("failed to dump labels: %s",
302*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
303*7fd79137SRobert Mustacchi 		g_exit = 1;
304*7fd79137SRobert Mustacchi 	}
305*7fd79137SRobert Mustacchi }
306*7fd79137SRobert Mustacchi 
307*7fd79137SRobert Mustacchi static int
308*7fd79137SRobert Mustacchi ctfdump_strings_cb(const char *s, void *arg)
309*7fd79137SRobert Mustacchi {
310*7fd79137SRobert Mustacchi 	size_t len = strlen(s) + 1;
311*7fd79137SRobert Mustacchi 	ulong_t *stroff = arg;
312*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STRINGS, "  [%lu] %s\n", *stroff,
313*7fd79137SRobert Mustacchi 	    *s == '\0' ? "\\0" : s);
314*7fd79137SRobert Mustacchi 	*stroff = *stroff + len;
315*7fd79137SRobert Mustacchi 	g_stats.cs_nstrings++;
316*7fd79137SRobert Mustacchi 	g_stats.cs_strsz += len;
317*7fd79137SRobert Mustacchi 	g_stats.cs_strmax = MAX(g_stats.cs_strmax, len);
318*7fd79137SRobert Mustacchi 	return (0);
319*7fd79137SRobert Mustacchi }
320*7fd79137SRobert Mustacchi 
321*7fd79137SRobert Mustacchi static void
322*7fd79137SRobert Mustacchi ctfdump_strings(void)
323*7fd79137SRobert Mustacchi {
324*7fd79137SRobert Mustacchi 	ulong_t stroff = 0;
325*7fd79137SRobert Mustacchi 
326*7fd79137SRobert Mustacchi 	ctfdump_title(CTFDUMP_STRINGS, "String Table");
327*7fd79137SRobert Mustacchi 	if (ctf_string_iter(g_fp, ctfdump_strings_cb, &stroff) == CTF_ERR) {
328*7fd79137SRobert Mustacchi 		warnx("failed to dump strings: %s",
329*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
330*7fd79137SRobert Mustacchi 		g_exit = 1;
331*7fd79137SRobert Mustacchi 	}
332*7fd79137SRobert Mustacchi }
333*7fd79137SRobert Mustacchi 
334*7fd79137SRobert Mustacchi static void
335*7fd79137SRobert Mustacchi ctfdump_stat_int(const char *name, ulong_t value)
336*7fd79137SRobert Mustacchi {
337*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "  %-36s= %lu\n", name, value);
338*7fd79137SRobert Mustacchi }
339*7fd79137SRobert Mustacchi 
340*7fd79137SRobert Mustacchi static void
341*7fd79137SRobert Mustacchi ctfdump_stat_fp(const char *name, float value)
342*7fd79137SRobert Mustacchi {
343*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "  %-36s= %.2f\n", name, value);
344*7fd79137SRobert Mustacchi }
345*7fd79137SRobert Mustacchi 
346*7fd79137SRobert Mustacchi static void
347*7fd79137SRobert Mustacchi ctfdump_stats(void)
348*7fd79137SRobert Mustacchi {
349*7fd79137SRobert Mustacchi 	int i;
350*7fd79137SRobert Mustacchi 	ulong_t sum;
351*7fd79137SRobert Mustacchi 
352*7fd79137SRobert Mustacchi 	ctfdump_title(CTFDUMP_STATS, "CTF Statistics");
353*7fd79137SRobert Mustacchi 
354*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of data objects", g_stats.cs_ndata);
355*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "\n");
356*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of functions", g_stats.cs_nfuncs);
357*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of function arguments",
358*7fd79137SRobert Mustacchi 	    g_stats.cs_nfuncargs);
359*7fd79137SRobert Mustacchi 	ctfdump_stat_int("maximum argument list length", g_stats.cs_nfuncmax);
360*7fd79137SRobert Mustacchi 	if (g_stats.cs_nfuncs != 0)
361*7fd79137SRobert Mustacchi 		ctfdump_stat_fp("average argument list length",
362*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_nfuncargs / (float)g_stats.cs_nfuncs);
363*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "\n");
364*7fd79137SRobert Mustacchi 
365*7fd79137SRobert Mustacchi 	sum = 0;
366*7fd79137SRobert Mustacchi 	for (i = 0; i < CTF_K_MAX; i++)
367*7fd79137SRobert Mustacchi 		sum += g_stats.cs_ntypes[i];
368*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of types", sum);
369*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of integers",
370*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_INTEGER]);
371*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of floats",
372*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_FLOAT]);
373*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of pointers",
374*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_POINTER]);
375*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of arrays",
376*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_ARRAY]);
377*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of func types",
378*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_FUNCTION]);
379*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of structs",
380*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_STRUCT]);
381*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of unions",
382*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_UNION]);
383*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of enums",
384*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_ENUM]);
385*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of forward tags",
386*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_FORWARD]);
387*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of typedefs",
388*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_TYPEDEF]);
389*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of volatile types",
390*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_VOLATILE]);
391*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of const types",
392*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_CONST]);
393*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of restrict types",
394*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_RESTRICT]);
395*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of unknowns (holes)",
396*7fd79137SRobert Mustacchi 	    g_stats.cs_ntypes[CTF_K_UNKNOWN]);
397*7fd79137SRobert Mustacchi 
398*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "\n");
399*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of struct members", g_stats.cs_nsmembs);
400*7fd79137SRobert Mustacchi 	ctfdump_stat_int("maximum number of struct members", g_stats.cs_nsmax);
401*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total size of all structs", g_stats.cs_structsz);
402*7fd79137SRobert Mustacchi 	ctfdump_stat_int("maximum size of a struct", g_stats.cs_sszmax);
403*7fd79137SRobert Mustacchi 	if (g_stats.cs_ntypes[CTF_K_STRUCT] != 0) {
404*7fd79137SRobert Mustacchi 		ctfdump_stat_fp("average number of struct members",
405*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_nsmembs /
406*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_ntypes[CTF_K_STRUCT]);
407*7fd79137SRobert Mustacchi 		ctfdump_stat_fp("average size of a struct",
408*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_structsz /
409*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_ntypes[CTF_K_STRUCT]);
410*7fd79137SRobert Mustacchi 	}
411*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "\n");
412*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of union members", g_stats.cs_numembs);
413*7fd79137SRobert Mustacchi 	ctfdump_stat_int("maximum number of union members", g_stats.cs_numax);
414*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total size of all unions", g_stats.cs_unionsz);
415*7fd79137SRobert Mustacchi 	ctfdump_stat_int("maximum size of a union", g_stats.cs_uszmax);
416*7fd79137SRobert Mustacchi 	if (g_stats.cs_ntypes[CTF_K_UNION] != 0) {
417*7fd79137SRobert Mustacchi 		ctfdump_stat_fp("average number of union members",
418*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_numembs /
419*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_ntypes[CTF_K_UNION]);
420*7fd79137SRobert Mustacchi 		ctfdump_stat_fp("average size of a union",
421*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_unionsz /
422*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_ntypes[CTF_K_UNION]);
423*7fd79137SRobert Mustacchi 	}
424*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "\n");
425*7fd79137SRobert Mustacchi 
426*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of enum members", g_stats.cs_nemembs);
427*7fd79137SRobert Mustacchi 	ctfdump_stat_int("maximum number of enum members", g_stats.cs_nemax);
428*7fd79137SRobert Mustacchi 	if (g_stats.cs_ntypes[CTF_K_ENUM] != 0) {
429*7fd79137SRobert Mustacchi 		ctfdump_stat_fp("average number of enum members",
430*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_nemembs /
431*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_ntypes[CTF_K_ENUM]);
432*7fd79137SRobert Mustacchi 	}
433*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "\n");
434*7fd79137SRobert Mustacchi 
435*7fd79137SRobert Mustacchi 	ctfdump_stat_int("total number of strings", g_stats.cs_nstrings);
436*7fd79137SRobert Mustacchi 	ctfdump_stat_int("bytes of string data", g_stats.cs_strsz);
437*7fd79137SRobert Mustacchi 	ctfdump_stat_int("maximum string length", g_stats.cs_strmax);
438*7fd79137SRobert Mustacchi 	if (g_stats.cs_nstrings != 0)
439*7fd79137SRobert Mustacchi 		ctfdump_stat_fp("average string length",
440*7fd79137SRobert Mustacchi 		    (float)g_stats.cs_strsz / (float)g_stats.cs_nstrings);
441*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_STATS, "\n");
442*7fd79137SRobert Mustacchi }
443*7fd79137SRobert Mustacchi 
444*7fd79137SRobert Mustacchi static void
445*7fd79137SRobert Mustacchi ctfdump_intenc_name(ctf_encoding_t *cte, char *buf, int len)
446*7fd79137SRobert Mustacchi {
447*7fd79137SRobert Mustacchi 	int off = 0;
448*7fd79137SRobert Mustacchi 	boolean_t space = B_FALSE;
449*7fd79137SRobert Mustacchi 
450*7fd79137SRobert Mustacchi 	if (cte->cte_format == 0 || (cte->cte_format &
451*7fd79137SRobert Mustacchi 	    ~(CTF_INT_SIGNED | CTF_INT_CHAR | CTF_INT_BOOL |
452*7fd79137SRobert Mustacchi 	    CTF_INT_VARARGS)) != 0) {
453*7fd79137SRobert Mustacchi 		(void) snprintf(buf, len, "0x%x", cte->cte_format);
454*7fd79137SRobert Mustacchi 		return;
455*7fd79137SRobert Mustacchi 	}
456*7fd79137SRobert Mustacchi 
457*7fd79137SRobert Mustacchi 	if (cte->cte_format & CTF_INT_SIGNED) {
458*7fd79137SRobert Mustacchi 		off += snprintf(buf + off, MAX(len - off, 0), "%sSIGNED",
459*7fd79137SRobert Mustacchi 		    space == B_TRUE ? " " : "");
460*7fd79137SRobert Mustacchi 		space = B_TRUE;
461*7fd79137SRobert Mustacchi 	}
462*7fd79137SRobert Mustacchi 
463*7fd79137SRobert Mustacchi 	if (cte->cte_format & CTF_INT_CHAR) {
464*7fd79137SRobert Mustacchi 		off += snprintf(buf + off, MAX(len - off, 0), "%sCHAR",
465*7fd79137SRobert Mustacchi 		    space == B_TRUE ? " " : "");
466*7fd79137SRobert Mustacchi 		space = B_TRUE;
467*7fd79137SRobert Mustacchi 	}
468*7fd79137SRobert Mustacchi 
469*7fd79137SRobert Mustacchi 	if (cte->cte_format & CTF_INT_BOOL) {
470*7fd79137SRobert Mustacchi 		off += snprintf(buf + off, MAX(len - off, 0), "%sBOOL",
471*7fd79137SRobert Mustacchi 		    space == B_TRUE ? " " : "");
472*7fd79137SRobert Mustacchi 		space = B_TRUE;
473*7fd79137SRobert Mustacchi 	}
474*7fd79137SRobert Mustacchi 
475*7fd79137SRobert Mustacchi 	if (cte->cte_format & CTF_INT_VARARGS) {
476*7fd79137SRobert Mustacchi 		off += snprintf(buf + off, MAX(len - off, 0), "%sVARARGS",
477*7fd79137SRobert Mustacchi 		    space == B_TRUE ? " " : "");
478*7fd79137SRobert Mustacchi 		space = B_TRUE;
479*7fd79137SRobert Mustacchi 	}
480*7fd79137SRobert Mustacchi }
481*7fd79137SRobert Mustacchi 
482*7fd79137SRobert Mustacchi static int
483*7fd79137SRobert Mustacchi ctfdump_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg)
484*7fd79137SRobert Mustacchi {
485*7fd79137SRobert Mustacchi 	int *count = arg;
486*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_TYPES, "\t%s type=%ld off=%lu\n", member, type,
487*7fd79137SRobert Mustacchi 	    off);
488*7fd79137SRobert Mustacchi 	*count = *count + 1;
489*7fd79137SRobert Mustacchi 	return (0);
490*7fd79137SRobert Mustacchi }
491*7fd79137SRobert Mustacchi 
492*7fd79137SRobert Mustacchi static int
493*7fd79137SRobert Mustacchi ctfdump_enum_cb(const char *name, int value, void *arg)
494*7fd79137SRobert Mustacchi {
495*7fd79137SRobert Mustacchi 	int *count = arg;
496*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_TYPES, "\t%s = %d\n", name, value);
497*7fd79137SRobert Mustacchi 	*count = *count + 1;
498*7fd79137SRobert Mustacchi 	return (0);
499*7fd79137SRobert Mustacchi }
500*7fd79137SRobert Mustacchi 
501*7fd79137SRobert Mustacchi static int
502*7fd79137SRobert Mustacchi ctfdump_types_cb(ctf_id_t id, boolean_t root, void *arg)
503*7fd79137SRobert Mustacchi {
504*7fd79137SRobert Mustacchi 	_NOTE(ARGUNUSED(arg));
505*7fd79137SRobert Mustacchi 	int kind, i, count;
506*7fd79137SRobert Mustacchi 	ctf_id_t ref;
507*7fd79137SRobert Mustacchi 	char name[MAX_NAMELEN], ienc[128];
508*7fd79137SRobert Mustacchi 	const char *encn;
509*7fd79137SRobert Mustacchi 	ctf_funcinfo_t ctc;
510*7fd79137SRobert Mustacchi 	ctf_arinfo_t ar;
511*7fd79137SRobert Mustacchi 	ctf_encoding_t cte;
512*7fd79137SRobert Mustacchi 	ssize_t size;
513*7fd79137SRobert Mustacchi 
514*7fd79137SRobert Mustacchi 	if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR)
515*7fd79137SRobert Mustacchi 		ctfdump_fatal("encountered malformed ctf, type %s does not "
516*7fd79137SRobert Mustacchi 		    "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
517*7fd79137SRobert Mustacchi 
518*7fd79137SRobert Mustacchi 	if (ctf_type_name(g_fp, id, name, sizeof (name)) == NULL) {
519*7fd79137SRobert Mustacchi 		if (ctf_errno(g_fp) != ECTF_NOPARENT)
520*7fd79137SRobert Mustacchi 			ctfdump_fatal("type %ld missing name: %s\n", id,
521*7fd79137SRobert Mustacchi 			    ctf_errmsg(ctf_errno(g_fp)));
522*7fd79137SRobert Mustacchi 		(void) snprintf(name, sizeof (name), "(unknown %s)",
523*7fd79137SRobert Mustacchi 		    ctf_kind_name(g_fp, kind));
524*7fd79137SRobert Mustacchi 	}
525*7fd79137SRobert Mustacchi 
526*7fd79137SRobert Mustacchi 	g_stats.cs_ntypes[kind]++;
527*7fd79137SRobert Mustacchi 	if (root == B_TRUE)
528*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "  <%ld> ", id);
529*7fd79137SRobert Mustacchi 	else
530*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "  [%ld] ", id);
531*7fd79137SRobert Mustacchi 
532*7fd79137SRobert Mustacchi 	switch (kind) {
533*7fd79137SRobert Mustacchi 	case CTF_K_UNKNOWN:
534*7fd79137SRobert Mustacchi 		break;
535*7fd79137SRobert Mustacchi 	case CTF_K_INTEGER:
536*7fd79137SRobert Mustacchi 		if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR)
537*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get encoding information "
538*7fd79137SRobert Mustacchi 			    "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
539*7fd79137SRobert Mustacchi 		ctfdump_intenc_name(&cte, ienc, sizeof (ienc));
540*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES,
541*7fd79137SRobert Mustacchi 		    "%s encoding=%s offset=%u bits=%u",
542*7fd79137SRobert Mustacchi 		    name, ienc, cte.cte_offset, cte.cte_bits);
543*7fd79137SRobert Mustacchi 		break;
544*7fd79137SRobert Mustacchi 	case CTF_K_FLOAT:
545*7fd79137SRobert Mustacchi 		if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR)
546*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get encoding information "
547*7fd79137SRobert Mustacchi 			    "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
548*7fd79137SRobert Mustacchi 		if (cte.cte_format < 1 || cte.cte_format > 12)
549*7fd79137SRobert Mustacchi 			encn = "unknown";
550*7fd79137SRobert Mustacchi 		else
551*7fd79137SRobert Mustacchi 			encn = ctfdump_fpenc[cte.cte_format];
552*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s encoding=%s offset=%u "
553*7fd79137SRobert Mustacchi 		    "bits=%u", name, encn, cte.cte_offset, cte.cte_bits);
554*7fd79137SRobert Mustacchi 		break;
555*7fd79137SRobert Mustacchi 	case CTF_K_POINTER:
556*7fd79137SRobert Mustacchi 		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
557*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get reference type for %s: "
558*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
559*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
560*7fd79137SRobert Mustacchi 		    ref);
561*7fd79137SRobert Mustacchi 		break;
562*7fd79137SRobert Mustacchi 	case CTF_K_ARRAY:
563*7fd79137SRobert Mustacchi 		if (ctf_array_info(g_fp, id, &ar) == CTF_ERR)
564*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get array information for "
565*7fd79137SRobert Mustacchi 			    "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
566*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s contents: %ld, index: %ld",
567*7fd79137SRobert Mustacchi 		    name, ar.ctr_contents, ar.ctr_index);
568*7fd79137SRobert Mustacchi 		break;
569*7fd79137SRobert Mustacchi 	case CTF_K_FUNCTION:
570*7fd79137SRobert Mustacchi 		if (ctf_func_info_by_id(g_fp, id, &ctc) == CTF_ERR)
571*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get function info for %s: "
572*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
573*7fd79137SRobert Mustacchi 		if (ctc.ctc_argc > 0) {
574*7fd79137SRobert Mustacchi 			ctfdump_fargs_grow(ctc.ctc_argc);
575*7fd79137SRobert Mustacchi 			if (ctf_func_args_by_id(g_fp, id, g_nfargc, g_fargc) ==
576*7fd79137SRobert Mustacchi 			    CTF_ERR)
577*7fd79137SRobert Mustacchi 				ctfdump_fatal("failed to get function "
578*7fd79137SRobert Mustacchi 				    "arguments for %s: %s\n", name,
579*7fd79137SRobert Mustacchi 				    ctf_errmsg(ctf_errno(g_fp)));
580*7fd79137SRobert Mustacchi 		}
581*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES,
582*7fd79137SRobert Mustacchi 		    "%s returns: %ld args: (", name, ctc.ctc_return);
583*7fd79137SRobert Mustacchi 		for (i = 0; i < ctc.ctc_argc; i++) {
584*7fd79137SRobert Mustacchi 			ctfdump_printf(CTFDUMP_TYPES, "%ld%s", g_fargc[i],
585*7fd79137SRobert Mustacchi 			    i + 1 == ctc.ctc_argc ? "" : ", ");
586*7fd79137SRobert Mustacchi 		}
587*7fd79137SRobert Mustacchi 		if (ctc.ctc_flags & CTF_FUNC_VARARG)
588*7fd79137SRobert Mustacchi 			ctfdump_printf(CTFDUMP_TYPES, "%s...",
589*7fd79137SRobert Mustacchi 			    ctc.ctc_argc == 0 ? "" : ", ");
590*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, ")");
591*7fd79137SRobert Mustacchi 		break;
592*7fd79137SRobert Mustacchi 	case CTF_K_STRUCT:
593*7fd79137SRobert Mustacchi 	case CTF_K_UNION:
594*7fd79137SRobert Mustacchi 		size = ctf_type_size(g_fp, id);
595*7fd79137SRobert Mustacchi 		if (size == CTF_ERR)
596*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get size of %s: %s\n", name,
597*7fd79137SRobert Mustacchi 			    ctf_errmsg(ctf_errno(g_fp)));
598*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s (%zd bytes)\n", name, size);
599*7fd79137SRobert Mustacchi 		count = 0;
600*7fd79137SRobert Mustacchi 		if (ctf_member_iter(g_fp, id, ctfdump_member_cb, &count) != 0)
601*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to iterate members of %s: %s\n",
602*7fd79137SRobert Mustacchi 			    name, ctf_errmsg(ctf_errno(g_fp)));
603*7fd79137SRobert Mustacchi 		if (kind == CTF_K_STRUCT) {
604*7fd79137SRobert Mustacchi 			g_stats.cs_nsmembs += count;
605*7fd79137SRobert Mustacchi 			g_stats.cs_nsmax = MAX(count, g_stats.cs_nsmax);
606*7fd79137SRobert Mustacchi 			g_stats.cs_structsz += size;
607*7fd79137SRobert Mustacchi 			g_stats.cs_sszmax = MAX(size, g_stats.cs_sszmax);
608*7fd79137SRobert Mustacchi 		} else {
609*7fd79137SRobert Mustacchi 			g_stats.cs_numembs += count;
610*7fd79137SRobert Mustacchi 			g_stats.cs_numax = MAX(count, g_stats.cs_numax);
611*7fd79137SRobert Mustacchi 			g_stats.cs_unionsz += size;
612*7fd79137SRobert Mustacchi 			g_stats.cs_uszmax = MAX(count, g_stats.cs_uszmax);
613*7fd79137SRobert Mustacchi 		}
614*7fd79137SRobert Mustacchi 		break;
615*7fd79137SRobert Mustacchi 	case CTF_K_ENUM:
616*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s\n", name);
617*7fd79137SRobert Mustacchi 		count = 0;
618*7fd79137SRobert Mustacchi 		if (ctf_enum_iter(g_fp, id, ctfdump_enum_cb, &count) != 0)
619*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to iterate enumerators of %s: "
620*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
621*7fd79137SRobert Mustacchi 		g_stats.cs_nemembs += count;
622*7fd79137SRobert Mustacchi 		g_stats.cs_nemax = MAX(g_stats.cs_nemax, count);
623*7fd79137SRobert Mustacchi 		break;
624*7fd79137SRobert Mustacchi 	case CTF_K_FORWARD:
625*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "forward %s\n", name);
626*7fd79137SRobert Mustacchi 		break;
627*7fd79137SRobert Mustacchi 	case CTF_K_TYPEDEF:
628*7fd79137SRobert Mustacchi 		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
629*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get reference type for %s: "
630*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
631*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "typedef %s refers to %ld", name,
632*7fd79137SRobert Mustacchi 		    ref);
633*7fd79137SRobert Mustacchi 		break;
634*7fd79137SRobert Mustacchi 	case CTF_K_VOLATILE:
635*7fd79137SRobert Mustacchi 		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
636*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get reference type for %s: "
637*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
638*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
639*7fd79137SRobert Mustacchi 		    ref);
640*7fd79137SRobert Mustacchi 		break;
641*7fd79137SRobert Mustacchi 	case CTF_K_CONST:
642*7fd79137SRobert Mustacchi 		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
643*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get reference type for %s: "
644*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
645*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
646*7fd79137SRobert Mustacchi 		    ref);
647*7fd79137SRobert Mustacchi 		break;
648*7fd79137SRobert Mustacchi 	case CTF_K_RESTRICT:
649*7fd79137SRobert Mustacchi 		if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR)
650*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get reference type for %s: "
651*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
652*7fd79137SRobert Mustacchi 		ctfdump_printf(CTFDUMP_TYPES, "%s refers to %ld", name,
653*7fd79137SRobert Mustacchi 		    ref);
654*7fd79137SRobert Mustacchi 		break;
655*7fd79137SRobert Mustacchi 	default:
656*7fd79137SRobert Mustacchi 		ctfdump_fatal("encountered unknown kind for type %s: %d\n",
657*7fd79137SRobert Mustacchi 		    name, kind);
658*7fd79137SRobert Mustacchi 	}
659*7fd79137SRobert Mustacchi 
660*7fd79137SRobert Mustacchi 	ctfdump_printf(CTFDUMP_TYPES, "\n");
661*7fd79137SRobert Mustacchi 
662*7fd79137SRobert Mustacchi 	return (0);
663*7fd79137SRobert Mustacchi }
664*7fd79137SRobert Mustacchi 
665*7fd79137SRobert Mustacchi static void
666*7fd79137SRobert Mustacchi ctfdump_types(void)
667*7fd79137SRobert Mustacchi {
668*7fd79137SRobert Mustacchi 	ctfdump_title(CTFDUMP_TYPES, "Types");
669*7fd79137SRobert Mustacchi 
670*7fd79137SRobert Mustacchi 	if (ctf_type_iter(g_fp, B_TRUE, ctfdump_types_cb, NULL) == CTF_ERR) {
671*7fd79137SRobert Mustacchi 		warnx("failed to dump types: %s",
672*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
673*7fd79137SRobert Mustacchi 		g_exit = 1;
674*7fd79137SRobert Mustacchi 	}
675*7fd79137SRobert Mustacchi }
676*7fd79137SRobert Mustacchi 
677*7fd79137SRobert Mustacchi /*
678*7fd79137SRobert Mustacchi  * C-style output. This is designed mainly for comparison purposes, and doesn't
679*7fd79137SRobert Mustacchi  * produce directly valid C:
680*7fd79137SRobert Mustacchi  *
681*7fd79137SRobert Mustacchi  * - the declarations are sorted alphabetically not semantically
682*7fd79137SRobert Mustacchi  * - anonymous enums without other users are elided (e.g. IDCS_PROBE_SENT)
683*7fd79137SRobert Mustacchi  * - doubly-pointed-to functions are wrong (e.g. in kiconv_ops_t)
684*7fd79137SRobert Mustacchi  * - anon unions declared within SOUs aren't expanded
685*7fd79137SRobert Mustacchi  * - function arguments aren't expanded recursively
686*7fd79137SRobert Mustacchi  */
687*7fd79137SRobert Mustacchi 
688*7fd79137SRobert Mustacchi static void
689*7fd79137SRobert Mustacchi ctfsrc_refname(ctf_id_t id, char *buf, size_t bufsize)
690*7fd79137SRobert Mustacchi {
691*7fd79137SRobert Mustacchi 	ctf_id_t ref;
692*7fd79137SRobert Mustacchi 
693*7fd79137SRobert Mustacchi 	if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) {
694*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to get reference type for %ld: "
695*7fd79137SRobert Mustacchi 		    "%s\n", id, ctf_errmsg(ctf_errno(g_fp)));
696*7fd79137SRobert Mustacchi 	}
697*7fd79137SRobert Mustacchi 
698*7fd79137SRobert Mustacchi 	(void) ctf_type_name(g_fp, ref, buf, bufsize);
699*7fd79137SRobert Mustacchi }
700*7fd79137SRobert Mustacchi 
701*7fd79137SRobert Mustacchi static int
702*7fd79137SRobert Mustacchi ctfsrc_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg)
703*7fd79137SRobert Mustacchi {
704*7fd79137SRobert Mustacchi 	_NOTE(ARGUNUSED(arg));
705*7fd79137SRobert Mustacchi 	char name[MAX_NAMELEN];
706*7fd79137SRobert Mustacchi 
707*7fd79137SRobert Mustacchi 	if (ctf_type_cname(g_fp, type, name, sizeof (name), member) == NULL) {
708*7fd79137SRobert Mustacchi 		if (ctf_errno(g_fp) != ECTF_NOPARENT) {
709*7fd79137SRobert Mustacchi 			ctfdump_fatal("type %ld missing name: %s\n", type,
710*7fd79137SRobert Mustacchi 			    ctf_errmsg(ctf_errno(g_fp)));
711*7fd79137SRobert Mustacchi 		}
712*7fd79137SRobert Mustacchi 
713*7fd79137SRobert Mustacchi 		(void) snprintf(name, sizeof (name), "unknown_t %s", member);
714*7fd79137SRobert Mustacchi 	}
715*7fd79137SRobert Mustacchi 
716*7fd79137SRobert Mustacchi 	/*
717*7fd79137SRobert Mustacchi 	 * A byte offset is friendlier, but we'll print bits too if it's not
718*7fd79137SRobert Mustacchi 	 * aligned (i.e. a bitfield).
719*7fd79137SRobert Mustacchi 	 */
720*7fd79137SRobert Mustacchi 	if (off % NBBY != 0) {
721*7fd79137SRobert Mustacchi 		(void) printf("\t%s; /* offset: %lu bytes (%lu bits) */\n",
722*7fd79137SRobert Mustacchi 		    name, off / NBBY, off);
723*7fd79137SRobert Mustacchi 	} else {
724*7fd79137SRobert Mustacchi 		(void) printf("\t%s; /* offset: %lu bytes */\n",
725*7fd79137SRobert Mustacchi 		    name, off / NBBY);
726*7fd79137SRobert Mustacchi 	}
727*7fd79137SRobert Mustacchi 	return (0);
728*7fd79137SRobert Mustacchi }
729*7fd79137SRobert Mustacchi 
730*7fd79137SRobert Mustacchi static int
731*7fd79137SRobert Mustacchi ctfsrc_enum_cb(const char *name, int value, void *arg)
732*7fd79137SRobert Mustacchi {
733*7fd79137SRobert Mustacchi 	_NOTE(ARGUNUSED(arg));
734*7fd79137SRobert Mustacchi 	(void) printf("\t%s = %d,\n", name, value);
735*7fd79137SRobert Mustacchi 	return (0);
736*7fd79137SRobert Mustacchi }
737*7fd79137SRobert Mustacchi 
738*7fd79137SRobert Mustacchi static int
739*7fd79137SRobert Mustacchi is_anon_refname(const char *refname)
740*7fd79137SRobert Mustacchi {
741*7fd79137SRobert Mustacchi 	return ((strcmp(refname, "struct ") == 0 ||
742*7fd79137SRobert Mustacchi 	    strcmp(refname, "union ") == 0 ||
743*7fd79137SRobert Mustacchi 	    strcmp(refname, "enum ") == 0));
744*7fd79137SRobert Mustacchi }
745*7fd79137SRobert Mustacchi 
746*7fd79137SRobert Mustacchi static int
747*7fd79137SRobert Mustacchi ctfsrc_collect_types_cb(ctf_id_t id, boolean_t root, void *arg)
748*7fd79137SRobert Mustacchi {
749*7fd79137SRobert Mustacchi 	_NOTE(ARGUNUSED(root, arg));
750*7fd79137SRobert Mustacchi 	(void) ctf_type_name(g_fp, id, idnames[id].ci_name,
751*7fd79137SRobert Mustacchi 	    sizeof (idnames[id].ci_name));
752*7fd79137SRobert Mustacchi 	idnames[id].ci_id = id;
753*7fd79137SRobert Mustacchi 	return (0);
754*7fd79137SRobert Mustacchi }
755*7fd79137SRobert Mustacchi 
756*7fd79137SRobert Mustacchi static void
757*7fd79137SRobert Mustacchi ctfsrc_type(ctf_id_t id, const char *name)
758*7fd79137SRobert Mustacchi {
759*7fd79137SRobert Mustacchi 	char refname[MAX_NAMELEN];
760*7fd79137SRobert Mustacchi 	ctf_id_t ref;
761*7fd79137SRobert Mustacchi 	ssize_t size;
762*7fd79137SRobert Mustacchi 	int kind;
763*7fd79137SRobert Mustacchi 
764*7fd79137SRobert Mustacchi 	if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) {
765*7fd79137SRobert Mustacchi 		ctfdump_fatal("encountered malformed ctf, type %s does not "
766*7fd79137SRobert Mustacchi 		    "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp)));
767*7fd79137SRobert Mustacchi 	}
768*7fd79137SRobert Mustacchi 
769*7fd79137SRobert Mustacchi 	switch (kind) {
770*7fd79137SRobert Mustacchi 	case CTF_K_STRUCT:
771*7fd79137SRobert Mustacchi 	case CTF_K_UNION:
772*7fd79137SRobert Mustacchi 		/*
773*7fd79137SRobert Mustacchi 		 * Delay printing anonymous SOUs; a later typedef will usually
774*7fd79137SRobert Mustacchi 		 * pick them up.
775*7fd79137SRobert Mustacchi 		 */
776*7fd79137SRobert Mustacchi 		if (is_anon_refname(name))
777*7fd79137SRobert Mustacchi 			break;
778*7fd79137SRobert Mustacchi 
779*7fd79137SRobert Mustacchi 		if ((size = ctf_type_size(g_fp, id)) == CTF_ERR) {
780*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get size of %s: %s\n", name,
781*7fd79137SRobert Mustacchi 			    ctf_errmsg(ctf_errno(g_fp)));
782*7fd79137SRobert Mustacchi 		}
783*7fd79137SRobert Mustacchi 
784*7fd79137SRobert Mustacchi 		(void) printf("%s { /* 0x%x bytes */\n", name, size);
785*7fd79137SRobert Mustacchi 
786*7fd79137SRobert Mustacchi 		if (ctf_member_iter(g_fp, id, ctfsrc_member_cb, NULL) != 0) {
787*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to iterate members of %s: %s\n",
788*7fd79137SRobert Mustacchi 			    name, ctf_errmsg(ctf_errno(g_fp)));
789*7fd79137SRobert Mustacchi 		}
790*7fd79137SRobert Mustacchi 
791*7fd79137SRobert Mustacchi 		(void) printf("};\n\n");
792*7fd79137SRobert Mustacchi 		break;
793*7fd79137SRobert Mustacchi 	case CTF_K_ENUM:
794*7fd79137SRobert Mustacchi 		/*
795*7fd79137SRobert Mustacchi 		 * This will throw away any anon enum that isn't followed by a
796*7fd79137SRobert Mustacchi 		 * typedef...
797*7fd79137SRobert Mustacchi 		 */
798*7fd79137SRobert Mustacchi 		if (is_anon_refname(name))
799*7fd79137SRobert Mustacchi 			break;
800*7fd79137SRobert Mustacchi 
801*7fd79137SRobert Mustacchi 		(void) printf("%s {\n", name);
802*7fd79137SRobert Mustacchi 
803*7fd79137SRobert Mustacchi 		if (ctf_enum_iter(g_fp, id, ctfsrc_enum_cb, NULL) != 0) {
804*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to iterate enumerators of %s: "
805*7fd79137SRobert Mustacchi 			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
806*7fd79137SRobert Mustacchi 		}
807*7fd79137SRobert Mustacchi 
808*7fd79137SRobert Mustacchi 		(void) printf("};\n\n");
809*7fd79137SRobert Mustacchi 		break;
810*7fd79137SRobert Mustacchi 	case CTF_K_TYPEDEF:
811*7fd79137SRobert Mustacchi 		ctfsrc_refname(id, refname, sizeof (refname));
812*7fd79137SRobert Mustacchi 
813*7fd79137SRobert Mustacchi 		if (!is_anon_refname(refname)) {
814*7fd79137SRobert Mustacchi 			(void) ctf_type_cname(g_fp,
815*7fd79137SRobert Mustacchi 			    ctf_type_reference(g_fp, id), refname,
816*7fd79137SRobert Mustacchi 			    sizeof (refname), name);
817*7fd79137SRobert Mustacchi 
818*7fd79137SRobert Mustacchi 			(void) printf("typedef %s;\n\n", refname);
819*7fd79137SRobert Mustacchi 			break;
820*7fd79137SRobert Mustacchi 		}
821*7fd79137SRobert Mustacchi 
822*7fd79137SRobert Mustacchi 		ref = ctf_type_reference(g_fp, id);
823*7fd79137SRobert Mustacchi 
824*7fd79137SRobert Mustacchi 		if (ctf_type_kind(g_fp, ref) == CTF_K_ENUM) {
825*7fd79137SRobert Mustacchi 			(void) printf("typedef enum {\n");
826*7fd79137SRobert Mustacchi 
827*7fd79137SRobert Mustacchi 			if (ctf_enum_iter(g_fp, ref,
828*7fd79137SRobert Mustacchi 			    ctfsrc_enum_cb, NULL) != 0) {
829*7fd79137SRobert Mustacchi 				ctfdump_fatal("failed to iterate enumerators "
830*7fd79137SRobert Mustacchi 				    "of %s: %s\n", refname,
831*7fd79137SRobert Mustacchi 				    ctf_errmsg(ctf_errno(g_fp)));
832*7fd79137SRobert Mustacchi 			}
833*7fd79137SRobert Mustacchi 
834*7fd79137SRobert Mustacchi 			(void) printf("} %s;\n\n", name);
835*7fd79137SRobert Mustacchi 		} else {
836*7fd79137SRobert Mustacchi 			if ((size = ctf_type_size(g_fp, ref)) == CTF_ERR) {
837*7fd79137SRobert Mustacchi 				ctfdump_fatal("failed to get size of %s: %s\n",
838*7fd79137SRobert Mustacchi 				    refname, ctf_errmsg(ctf_errno(g_fp)));
839*7fd79137SRobert Mustacchi 			}
840*7fd79137SRobert Mustacchi 
841*7fd79137SRobert Mustacchi 			(void) printf("typedef %s{ /* 0x%zx bytes */\n",
842*7fd79137SRobert Mustacchi 			    refname, size);
843*7fd79137SRobert Mustacchi 
844*7fd79137SRobert Mustacchi 			if (ctf_member_iter(g_fp, ref,
845*7fd79137SRobert Mustacchi 			    ctfsrc_member_cb, NULL) != 0) {
846*7fd79137SRobert Mustacchi 				ctfdump_fatal("failed to iterate members "
847*7fd79137SRobert Mustacchi 				    "of %s: %s\n", refname,
848*7fd79137SRobert Mustacchi 				    ctf_errmsg(ctf_errno(g_fp)));
849*7fd79137SRobert Mustacchi 			}
850*7fd79137SRobert Mustacchi 
851*7fd79137SRobert Mustacchi 			(void) printf("} %s;\n\n", name);
852*7fd79137SRobert Mustacchi 		}
853*7fd79137SRobert Mustacchi 
854*7fd79137SRobert Mustacchi 		break;
855*7fd79137SRobert Mustacchi 	case CTF_K_FORWARD:
856*7fd79137SRobert Mustacchi 		(void) printf("%s;\n\n", name);
857*7fd79137SRobert Mustacchi 		break;
858*7fd79137SRobert Mustacchi 	case CTF_K_UNKNOWN:
859*7fd79137SRobert Mustacchi 	case CTF_K_INTEGER:
860*7fd79137SRobert Mustacchi 	case CTF_K_FLOAT:
861*7fd79137SRobert Mustacchi 	case CTF_K_POINTER:
862*7fd79137SRobert Mustacchi 	case CTF_K_ARRAY:
863*7fd79137SRobert Mustacchi 	case CTF_K_FUNCTION:
864*7fd79137SRobert Mustacchi 	case CTF_K_VOLATILE:
865*7fd79137SRobert Mustacchi 	case CTF_K_CONST:
866*7fd79137SRobert Mustacchi 	case CTF_K_RESTRICT:
867*7fd79137SRobert Mustacchi 		break;
868*7fd79137SRobert Mustacchi 	default:
869*7fd79137SRobert Mustacchi 		ctfdump_fatal("encountered unknown kind for type %s: %d\n",
870*7fd79137SRobert Mustacchi 		    name, kind);
871*7fd79137SRobert Mustacchi 		break;
872*7fd79137SRobert Mustacchi 	}
873*7fd79137SRobert Mustacchi }
874*7fd79137SRobert Mustacchi 
875*7fd79137SRobert Mustacchi static int
876*7fd79137SRobert Mustacchi ctfsrc_collect_objects_cb(const char *name, ctf_id_t id,
877*7fd79137SRobert Mustacchi     ulong_t symidx, void *arg)
878*7fd79137SRobert Mustacchi {
879*7fd79137SRobert Mustacchi 	size_t *count = arg;
880*7fd79137SRobert Mustacchi 
881*7fd79137SRobert Mustacchi 	/* local static vars can have an unknown ID */
882*7fd79137SRobert Mustacchi 	if (id == 0)
883*7fd79137SRobert Mustacchi 		return (0);
884*7fd79137SRobert Mustacchi 
885*7fd79137SRobert Mustacchi 	(void) strlcpy(idnames[*count].ci_name, name,
886*7fd79137SRobert Mustacchi 	    sizeof (idnames[*count].ci_name));
887*7fd79137SRobert Mustacchi 	idnames[*count].ci_id = id;
888*7fd79137SRobert Mustacchi 	idnames[*count].ci_symidx = symidx;
889*7fd79137SRobert Mustacchi 	*count = *count + 1;
890*7fd79137SRobert Mustacchi 	return (0);
891*7fd79137SRobert Mustacchi }
892*7fd79137SRobert Mustacchi 
893*7fd79137SRobert Mustacchi static void
894*7fd79137SRobert Mustacchi ctfsrc_object(ctf_id_t id, const char *name)
895*7fd79137SRobert Mustacchi {
896*7fd79137SRobert Mustacchi 	char tname[MAX_NAMELEN];
897*7fd79137SRobert Mustacchi 
898*7fd79137SRobert Mustacchi 	if (ctf_type_cname(g_fp, id, tname, sizeof (tname), name) == NULL) {
899*7fd79137SRobert Mustacchi 		if (ctf_errno(g_fp) != ECTF_NOPARENT) {
900*7fd79137SRobert Mustacchi 			ctfdump_fatal("type %ld missing name: %s\n", id,
901*7fd79137SRobert Mustacchi 			    ctf_errmsg(ctf_errno(g_fp)));
902*7fd79137SRobert Mustacchi 		}
903*7fd79137SRobert Mustacchi 		(void) snprintf(tname, sizeof (tname), "unknown_t %s", name);
904*7fd79137SRobert Mustacchi 	}
905*7fd79137SRobert Mustacchi 
906*7fd79137SRobert Mustacchi 	(void) printf("extern %s;\n", tname);
907*7fd79137SRobert Mustacchi }
908*7fd79137SRobert Mustacchi 
909*7fd79137SRobert Mustacchi static int
910*7fd79137SRobert Mustacchi ctfsrc_collect_functions_cb(const char *name, ulong_t symidx,
911*7fd79137SRobert Mustacchi     ctf_funcinfo_t *ctc, void *arg)
912*7fd79137SRobert Mustacchi {
913*7fd79137SRobert Mustacchi 	size_t *count = arg;
914*7fd79137SRobert Mustacchi 
915*7fd79137SRobert Mustacchi 	(void) strlcpy(idnames[*count].ci_name, name,
916*7fd79137SRobert Mustacchi 	    sizeof (idnames[*count].ci_name));
917*7fd79137SRobert Mustacchi 	bcopy(ctc, &idnames[*count].ci_funcinfo, sizeof (*ctc));
918*7fd79137SRobert Mustacchi 	idnames[*count].ci_id = 0;
919*7fd79137SRobert Mustacchi 	idnames[*count].ci_symidx = symidx;
920*7fd79137SRobert Mustacchi 	*count = *count + 1;
921*7fd79137SRobert Mustacchi 	return (0);
922*7fd79137SRobert Mustacchi }
923*7fd79137SRobert Mustacchi 
924*7fd79137SRobert Mustacchi static void
925*7fd79137SRobert Mustacchi ctfsrc_function(ctf_idname_t *idn)
926*7fd79137SRobert Mustacchi {
927*7fd79137SRobert Mustacchi 	ctf_funcinfo_t *cfi = &idn->ci_funcinfo;
928*7fd79137SRobert Mustacchi 	char name[MAX_NAMELEN] = "unknown_t";
929*7fd79137SRobert Mustacchi 
930*7fd79137SRobert Mustacchi 	(void) ctf_type_name(g_fp, cfi->ctc_return, name, sizeof (name));
931*7fd79137SRobert Mustacchi 
932*7fd79137SRobert Mustacchi 	(void) printf("extern %s %s(", name, idn->ci_name);
933*7fd79137SRobert Mustacchi 
934*7fd79137SRobert Mustacchi 	if (cfi->ctc_argc != 0) {
935*7fd79137SRobert Mustacchi 		ctfdump_fargs_grow(cfi->ctc_argc);
936*7fd79137SRobert Mustacchi 		if (ctf_func_args(g_fp, idn->ci_symidx,
937*7fd79137SRobert Mustacchi 		    g_nfargc, g_fargc) == CTF_ERR) {
938*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to get arguments for function "
939*7fd79137SRobert Mustacchi 			    "%s: %s\n", idn->ci_name,
940*7fd79137SRobert Mustacchi 			    ctf_errmsg(ctf_errno(g_fp)));
941*7fd79137SRobert Mustacchi 		}
942*7fd79137SRobert Mustacchi 
943*7fd79137SRobert Mustacchi 		size_t i;
944*7fd79137SRobert Mustacchi 		for (i = 0; i < cfi->ctc_argc; i++) {
945*7fd79137SRobert Mustacchi 			ctf_id_t aid = g_fargc[i];
946*7fd79137SRobert Mustacchi 
947*7fd79137SRobert Mustacchi 			name[0] = '\0';
948*7fd79137SRobert Mustacchi 
949*7fd79137SRobert Mustacchi 			(void) ctf_type_name(g_fp, aid, name, sizeof (name));
950*7fd79137SRobert Mustacchi 
951*7fd79137SRobert Mustacchi 			(void) printf("%s%s", name,
952*7fd79137SRobert Mustacchi 			    i + 1 == cfi->ctc_argc ? "" : ", ");
953*7fd79137SRobert Mustacchi 		}
954*7fd79137SRobert Mustacchi 	} else {
955*7fd79137SRobert Mustacchi 		if (!(cfi->ctc_flags & CTF_FUNC_VARARG))
956*7fd79137SRobert Mustacchi 			(void) printf("void");
957*7fd79137SRobert Mustacchi 	}
958*7fd79137SRobert Mustacchi 
959*7fd79137SRobert Mustacchi 	if (cfi->ctc_flags & CTF_FUNC_VARARG)
960*7fd79137SRobert Mustacchi 		(void) printf("%s...", cfi->ctc_argc == 0 ? "" : ", ");
961*7fd79137SRobert Mustacchi 
962*7fd79137SRobert Mustacchi 	(void) printf(");\n");
963*7fd79137SRobert Mustacchi }
964*7fd79137SRobert Mustacchi 
965*7fd79137SRobert Mustacchi static int
966*7fd79137SRobert Mustacchi idname_compare(const void *lhs, const void *rhs)
967*7fd79137SRobert Mustacchi {
968*7fd79137SRobert Mustacchi 	return (strcmp(((ctf_idname_t *)lhs)->ci_name,
969*7fd79137SRobert Mustacchi 	    ((ctf_idname_t *)rhs)->ci_name));
970*7fd79137SRobert Mustacchi }
971*7fd79137SRobert Mustacchi 
972*7fd79137SRobert Mustacchi static void
973*7fd79137SRobert Mustacchi ctfdump_source(void)
974*7fd79137SRobert Mustacchi {
975*7fd79137SRobert Mustacchi 	ulong_t nr_syms = ctf_nr_syms(g_fp);
976*7fd79137SRobert Mustacchi 	ctf_id_t max_id = ctf_max_id(g_fp);
977*7fd79137SRobert Mustacchi 	size_t count = 0;
978*7fd79137SRobert Mustacchi 
979*7fd79137SRobert Mustacchi 	(void) printf("/* Types */\n\n");
980*7fd79137SRobert Mustacchi 
981*7fd79137SRobert Mustacchi 	if ((idnames = calloc(max_id + 1, sizeof (idnames[0]))) == NULL) {
982*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to alloc idnames: %s\n",
983*7fd79137SRobert Mustacchi 		    strerror(errno));
984*7fd79137SRobert Mustacchi 	}
985*7fd79137SRobert Mustacchi 
986*7fd79137SRobert Mustacchi 	if (ctf_type_iter(g_fp, B_FALSE, ctfsrc_collect_types_cb,
987*7fd79137SRobert Mustacchi 	    idnames) == CTF_ERR) {
988*7fd79137SRobert Mustacchi 		warnx("failed to collect types: %s",
989*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
990*7fd79137SRobert Mustacchi 		g_exit = 1;
991*7fd79137SRobert Mustacchi 	}
992*7fd79137SRobert Mustacchi 
993*7fd79137SRobert Mustacchi 	qsort(idnames, max_id, sizeof (ctf_idname_t), idname_compare);
994*7fd79137SRobert Mustacchi 
995*7fd79137SRobert Mustacchi 	size_t i;
996*7fd79137SRobert Mustacchi 	for (i = 0; i < max_id; i++) {
997*7fd79137SRobert Mustacchi 		if (idnames[i].ci_id != 0)
998*7fd79137SRobert Mustacchi 			ctfsrc_type(idnames[i].ci_id, idnames[i].ci_name);
999*7fd79137SRobert Mustacchi 	}
1000*7fd79137SRobert Mustacchi 
1001*7fd79137SRobert Mustacchi 	free(idnames);
1002*7fd79137SRobert Mustacchi 
1003*7fd79137SRobert Mustacchi 	(void) printf("\n\n/* Data Objects */\n\n");
1004*7fd79137SRobert Mustacchi 
1005*7fd79137SRobert Mustacchi 	if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) {
1006*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to alloc idnames: %s\n",
1007*7fd79137SRobert Mustacchi 		    strerror(errno));
1008*7fd79137SRobert Mustacchi 	}
1009*7fd79137SRobert Mustacchi 
1010*7fd79137SRobert Mustacchi 	if (ctf_object_iter(g_fp, ctfsrc_collect_objects_cb,
1011*7fd79137SRobert Mustacchi 	    &count) == CTF_ERR) {
1012*7fd79137SRobert Mustacchi 		warnx("failed to collect objects: %s",
1013*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
1014*7fd79137SRobert Mustacchi 		g_exit = 1;
1015*7fd79137SRobert Mustacchi 	}
1016*7fd79137SRobert Mustacchi 
1017*7fd79137SRobert Mustacchi 	qsort(idnames, count, sizeof (ctf_idname_t), idname_compare);
1018*7fd79137SRobert Mustacchi 
1019*7fd79137SRobert Mustacchi 	for (i = 0; i < count; i++)
1020*7fd79137SRobert Mustacchi 		ctfsrc_object(idnames[i].ci_id, idnames[i].ci_name);
1021*7fd79137SRobert Mustacchi 
1022*7fd79137SRobert Mustacchi 	free(idnames);
1023*7fd79137SRobert Mustacchi 
1024*7fd79137SRobert Mustacchi 	(void) printf("\n\n/* Functions */\n\n");
1025*7fd79137SRobert Mustacchi 
1026*7fd79137SRobert Mustacchi 	if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) {
1027*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to alloc idnames: %s\n",
1028*7fd79137SRobert Mustacchi 		    strerror(errno));
1029*7fd79137SRobert Mustacchi 	}
1030*7fd79137SRobert Mustacchi 
1031*7fd79137SRobert Mustacchi 	count = 0;
1032*7fd79137SRobert Mustacchi 
1033*7fd79137SRobert Mustacchi 	if (ctf_function_iter(g_fp, ctfsrc_collect_functions_cb,
1034*7fd79137SRobert Mustacchi 	    &count) == CTF_ERR) {
1035*7fd79137SRobert Mustacchi 		warnx("failed to collect functions: %s",
1036*7fd79137SRobert Mustacchi 		    ctf_errmsg(ctf_errno(g_fp)));
1037*7fd79137SRobert Mustacchi 		g_exit = 1;
1038*7fd79137SRobert Mustacchi 	}
1039*7fd79137SRobert Mustacchi 
1040*7fd79137SRobert Mustacchi 	qsort(idnames, count, sizeof (ctf_idname_t), idname_compare);
1041*7fd79137SRobert Mustacchi 
1042*7fd79137SRobert Mustacchi 	for (i = 0; i < count; i++)
1043*7fd79137SRobert Mustacchi 		ctfsrc_function(&idnames[i]);
1044*7fd79137SRobert Mustacchi 
1045*7fd79137SRobert Mustacchi 	free(idnames);
1046*7fd79137SRobert Mustacchi }
1047*7fd79137SRobert Mustacchi 
1048*7fd79137SRobert Mustacchi static void
1049*7fd79137SRobert Mustacchi ctfdump_output(const char *out)
1050*7fd79137SRobert Mustacchi {
1051*7fd79137SRobert Mustacchi 	int fd, ret;
1052*7fd79137SRobert Mustacchi 	const void *data;
1053*7fd79137SRobert Mustacchi 	size_t len;
1054*7fd79137SRobert Mustacchi 
1055*7fd79137SRobert Mustacchi 	ctf_dataptr(g_fp, &data, &len);
1056*7fd79137SRobert Mustacchi 	if ((fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
1057*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to open output file %s: %s\n", out,
1058*7fd79137SRobert Mustacchi 		    strerror(errno));
1059*7fd79137SRobert Mustacchi 
1060*7fd79137SRobert Mustacchi 	while (len > 0) {
1061*7fd79137SRobert Mustacchi 		ret = write(fd, data, len);
1062*7fd79137SRobert Mustacchi 		if (ret == -1 && errno == EINTR)
1063*7fd79137SRobert Mustacchi 			continue;
1064*7fd79137SRobert Mustacchi 		else if (ret == -1 && (errno == EFAULT || errno == EBADF))
1065*7fd79137SRobert Mustacchi 			abort();
1066*7fd79137SRobert Mustacchi 		else if (ret == -1)
1067*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to write to %s: %s\n", out,
1068*7fd79137SRobert Mustacchi 			    strerror(errno));
1069*7fd79137SRobert Mustacchi 		data = ((char *)data) + ret;
1070*7fd79137SRobert Mustacchi 		len -= ret;
1071*7fd79137SRobert Mustacchi 	}
1072*7fd79137SRobert Mustacchi 
1073*7fd79137SRobert Mustacchi 	do {
1074*7fd79137SRobert Mustacchi 		ret = close(fd);
1075*7fd79137SRobert Mustacchi 	} while (ret == -1 && errno == EINTR);
1076*7fd79137SRobert Mustacchi 	if (ret != 0 && errno == EBADF)
1077*7fd79137SRobert Mustacchi 		abort();
1078*7fd79137SRobert Mustacchi 	if (ret != 0)
1079*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to close %s: %s\n", out, strerror(errno));
1080*7fd79137SRobert Mustacchi }
1081*7fd79137SRobert Mustacchi 
1082*7fd79137SRobert Mustacchi int
1083*7fd79137SRobert Mustacchi main(int argc, char *argv[])
1084*7fd79137SRobert Mustacchi {
1085*7fd79137SRobert Mustacchi 	int c, fd, err;
1086*7fd79137SRobert Mustacchi 	const char *ufile = NULL, *parent = NULL;
1087*7fd79137SRobert Mustacchi 
1088*7fd79137SRobert Mustacchi 	g_progname = basename(argv[0]);
1089*7fd79137SRobert Mustacchi 	while ((c = getopt(argc, argv, ":cdfhlp:sStu:")) != -1) {
1090*7fd79137SRobert Mustacchi 		switch (c) {
1091*7fd79137SRobert Mustacchi 		case 'c':
1092*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_SOURCE;
1093*7fd79137SRobert Mustacchi 			break;
1094*7fd79137SRobert Mustacchi 		case 'd':
1095*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_OBJECTS;
1096*7fd79137SRobert Mustacchi 			break;
1097*7fd79137SRobert Mustacchi 		case 'f':
1098*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_FUNCTIONS;
1099*7fd79137SRobert Mustacchi 			break;
1100*7fd79137SRobert Mustacchi 		case 'h':
1101*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_HEADER;
1102*7fd79137SRobert Mustacchi 			break;
1103*7fd79137SRobert Mustacchi 		case 'l':
1104*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_LABELS;
1105*7fd79137SRobert Mustacchi 			break;
1106*7fd79137SRobert Mustacchi 		case 'p':
1107*7fd79137SRobert Mustacchi 			parent = optarg;
1108*7fd79137SRobert Mustacchi 			break;
1109*7fd79137SRobert Mustacchi 		case 's':
1110*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_STRINGS;
1111*7fd79137SRobert Mustacchi 			break;
1112*7fd79137SRobert Mustacchi 		case 'S':
1113*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_STATS;
1114*7fd79137SRobert Mustacchi 			break;
1115*7fd79137SRobert Mustacchi 		case 't':
1116*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_TYPES;
1117*7fd79137SRobert Mustacchi 			break;
1118*7fd79137SRobert Mustacchi 		case 'u':
1119*7fd79137SRobert Mustacchi 			g_dump |= CTFDUMP_OUTPUT;
1120*7fd79137SRobert Mustacchi 			ufile = optarg;
1121*7fd79137SRobert Mustacchi 			break;
1122*7fd79137SRobert Mustacchi 		case '?':
1123*7fd79137SRobert Mustacchi 			ctfdump_usage("Unknown option: -%c\n", optopt);
1124*7fd79137SRobert Mustacchi 			return (2);
1125*7fd79137SRobert Mustacchi 		case ':':
1126*7fd79137SRobert Mustacchi 			ctfdump_usage("Option -%c requires an operand\n",
1127*7fd79137SRobert Mustacchi 			    optopt);
1128*7fd79137SRobert Mustacchi 			return (2);
1129*7fd79137SRobert Mustacchi 		}
1130*7fd79137SRobert Mustacchi 	}
1131*7fd79137SRobert Mustacchi 
1132*7fd79137SRobert Mustacchi 	argc -= optind;
1133*7fd79137SRobert Mustacchi 	argv += optind;
1134*7fd79137SRobert Mustacchi 
1135*7fd79137SRobert Mustacchi 	if ((g_dump & CTFDUMP_SOURCE) && !!(g_dump & ~CTFDUMP_SOURCE)) {
1136*7fd79137SRobert Mustacchi 		ctfdump_usage("-c must be specified on its own\n");
1137*7fd79137SRobert Mustacchi 		return (2);
1138*7fd79137SRobert Mustacchi 	}
1139*7fd79137SRobert Mustacchi 
1140*7fd79137SRobert Mustacchi 	/*
1141*7fd79137SRobert Mustacchi 	 * Dump all information except C source by default.
1142*7fd79137SRobert Mustacchi 	 */
1143*7fd79137SRobert Mustacchi 	if (g_dump == 0)
1144*7fd79137SRobert Mustacchi 		g_dump = CTFDUMP_DEFAULT;
1145*7fd79137SRobert Mustacchi 
1146*7fd79137SRobert Mustacchi 	if (argc != 1) {
1147*7fd79137SRobert Mustacchi 		ctfdump_usage("no file to dump\n");
1148*7fd79137SRobert Mustacchi 		return (2);
1149*7fd79137SRobert Mustacchi 	}
1150*7fd79137SRobert Mustacchi 
1151*7fd79137SRobert Mustacchi 	if ((fd = open(argv[0], O_RDONLY)) < 0)
1152*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to open file %s: %s\n", argv[0],
1153*7fd79137SRobert Mustacchi 		    strerror(errno));
1154*7fd79137SRobert Mustacchi 
1155*7fd79137SRobert Mustacchi 	g_fp = ctf_fdopen(fd, &err);
1156*7fd79137SRobert Mustacchi 	if (g_fp == NULL)
1157*7fd79137SRobert Mustacchi 		ctfdump_fatal("failed to open file %s: %s\n", argv[0],
1158*7fd79137SRobert Mustacchi 		    ctf_errmsg(err));
1159*7fd79137SRobert Mustacchi 
1160*7fd79137SRobert Mustacchi 	/*
1161*7fd79137SRobert Mustacchi 	 * Check to see if this file needs a parent. If it does not and we were
1162*7fd79137SRobert Mustacchi 	 * given one, that should be an error. If it does need one and the
1163*7fd79137SRobert Mustacchi 	 * parent is not specified, that is fine, we just won't know how to
1164*7fd79137SRobert Mustacchi 	 * find child types. If we are given a parent, check at least that the
1165*7fd79137SRobert Mustacchi 	 * labels match.
1166*7fd79137SRobert Mustacchi 	 */
1167*7fd79137SRobert Mustacchi 	if (ctf_parent_name(g_fp) == NULL) {
1168*7fd79137SRobert Mustacchi 		if (parent != NULL)
1169*7fd79137SRobert Mustacchi 			ctfdump_fatal("cannot use %s as a parent file, %s is "
1170*7fd79137SRobert Mustacchi 			    "not a child\n", parent, argv[0]);
1171*7fd79137SRobert Mustacchi 	} else if (parent != NULL) {
1172*7fd79137SRobert Mustacchi 		const char *explabel, *label;
1173*7fd79137SRobert Mustacchi 		ctf_file_t *pfp = ctf_open(parent, &err);
1174*7fd79137SRobert Mustacchi 
1175*7fd79137SRobert Mustacchi 		if (pfp == NULL)
1176*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to open parent file %s: %s\n",
1177*7fd79137SRobert Mustacchi 			    parent, ctf_errmsg(err));
1178*7fd79137SRobert Mustacchi 
1179*7fd79137SRobert Mustacchi 		/*
1180*7fd79137SRobert Mustacchi 		 * Before we import the parent into the child, check that the
1181*7fd79137SRobert Mustacchi 		 * labels match. While there is also the notion of the parent
1182*7fd79137SRobert Mustacchi 		 * name, it's less straightforward to match that. Require that
1183*7fd79137SRobert Mustacchi 		 * labels match.
1184*7fd79137SRobert Mustacchi 		 */
1185*7fd79137SRobert Mustacchi 		explabel = ctf_parent_label(g_fp);
1186*7fd79137SRobert Mustacchi 		label = ctf_label_topmost(pfp);
1187*7fd79137SRobert Mustacchi 		if (explabel == NULL || label == NULL ||
1188*7fd79137SRobert Mustacchi 		    strcmp(explabel, label) != 0) {
1189*7fd79137SRobert Mustacchi 			if (label == NULL)
1190*7fd79137SRobert Mustacchi 				label = "<missing>";
1191*7fd79137SRobert Mustacchi 			if (explabel == NULL)
1192*7fd79137SRobert Mustacchi 				explabel = "<missing>";
1193*7fd79137SRobert Mustacchi 			ctfdump_fatal("label mismatch between parent %s and "
1194*7fd79137SRobert Mustacchi 			    "child %s, parent has %s, child expects %s\n",
1195*7fd79137SRobert Mustacchi 			    parent, argv[0], label, explabel);
1196*7fd79137SRobert Mustacchi 		}
1197*7fd79137SRobert Mustacchi 
1198*7fd79137SRobert Mustacchi 		if (ctf_import(g_fp, pfp) != 0)
1199*7fd79137SRobert Mustacchi 			ctfdump_fatal("failed to import parent %s: %s\n",
1200*7fd79137SRobert Mustacchi 			    parent, ctf_errmsg(ctf_errno(g_fp)));
1201*7fd79137SRobert Mustacchi 	}
1202*7fd79137SRobert Mustacchi 
1203*7fd79137SRobert Mustacchi 	if (g_dump & CTFDUMP_SOURCE) {
1204*7fd79137SRobert Mustacchi 		ctfdump_source();
1205*7fd79137SRobert Mustacchi 		return (0);
1206*7fd79137SRobert Mustacchi 	}
1207*7fd79137SRobert Mustacchi 
1208*7fd79137SRobert Mustacchi 	/*
1209*7fd79137SRobert Mustacchi 	 * If stats is set, we must run through everything exect CTFDUMP_OUTPUT.
1210*7fd79137SRobert Mustacchi 	 * We also do CTFDUMP_STATS last as a result.
1211*7fd79137SRobert Mustacchi 	 */
1212*7fd79137SRobert Mustacchi 	if (g_dump & CTFDUMP_HEADER)
1213*7fd79137SRobert Mustacchi 		ctfdump_header();
1214*7fd79137SRobert Mustacchi 
1215*7fd79137SRobert Mustacchi 	if (g_dump & (CTFDUMP_LABELS | CTFDUMP_STATS))
1216*7fd79137SRobert Mustacchi 		ctfdump_labels();
1217*7fd79137SRobert Mustacchi 
1218*7fd79137SRobert Mustacchi 	if (g_dump & (CTFDUMP_OBJECTS | CTFDUMP_STATS))
1219*7fd79137SRobert Mustacchi 		ctfdump_objects();
1220*7fd79137SRobert Mustacchi 
1221*7fd79137SRobert Mustacchi 	if (g_dump & (CTFDUMP_FUNCTIONS | CTFDUMP_STATS))
1222*7fd79137SRobert Mustacchi 		ctfdump_functions();
1223*7fd79137SRobert Mustacchi 
1224*7fd79137SRobert Mustacchi 	if (g_dump & (CTFDUMP_TYPES | CTFDUMP_STATS))
1225*7fd79137SRobert Mustacchi 		ctfdump_types();
1226*7fd79137SRobert Mustacchi 
1227*7fd79137SRobert Mustacchi 	if (g_dump & (CTFDUMP_STRINGS | CTFDUMP_STATS))
1228*7fd79137SRobert Mustacchi 		ctfdump_strings();
1229*7fd79137SRobert Mustacchi 
1230*7fd79137SRobert Mustacchi 	if (g_dump & CTFDUMP_STATS)
1231*7fd79137SRobert Mustacchi 		ctfdump_stats();
1232*7fd79137SRobert Mustacchi 
1233*7fd79137SRobert Mustacchi 	if (g_dump & CTFDUMP_OUTPUT)
1234*7fd79137SRobert Mustacchi 		ctfdump_output(ufile);
1235*7fd79137SRobert Mustacchi 
1236*7fd79137SRobert Mustacchi 	return (g_exit);
1237*7fd79137SRobert Mustacchi }
1238