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