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