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