static int ctfsrc_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg) { _NOTE(ARGUNUSED(arg)); char name[MAX_NAMELEN]; if (ctf_type_cname(g_fp, type, name, sizeof (name), member) == NULL) { if (ctf_errno(g_fp) != ECTF_NOPARENT) { ctfdump_fatal("type %ld missing name: %s\n", type, ctf_errmsg(ctf_errno(g_fp))); } (void) snprintf(name, sizeof (name), "unknown_t %s", member); } /* * A byte offset is friendlier, but we'll print bits too if it's not * aligned (i.e. a bitfield). */ if (off % NBBY != 0) { (void) printf("\t%s; /* offset: %lu bytes (%lu bits) */\n", name, off / NBBY, off); } else { (void) printf("\t%s; /* offset: %lu bytes */\n", name, off / NBBY); } return (0); }
/* * When setting the strsize option, set the option in the dt_options array * using dt_opt_size() as usual, and then update the definition of the CTF * type for the D intrinsic "string" to be an array of the corresponding size. * If any errors occur, reset dt_options[option] to its previous value. */ static int dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) { dtrace_optval_t val = dtp->dt_options[option]; ctf_file_t *fp = DT_STR_CTFP(dtp); ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp)); ctf_arinfo_t r; if (dt_opt_size(dtp, arg, option) != 0) return (-1); /* dt_errno is set for us */ if (dtp->dt_options[option] > UINT_MAX) { dtp->dt_options[option] = val; return (dt_set_errno(dtp, EOVERFLOW)); } if (ctf_array_info(fp, type, &r) == CTF_ERR) { dtp->dt_options[option] = val; dtp->dt_ctferr = ctf_errno(fp); return (dt_set_errno(dtp, EDT_CTF)); } r.ctr_nelems = (uint_t)dtp->dt_options[option]; if (ctf_set_array(fp, type, &r) == CTF_ERR || ctf_update(fp) == CTF_ERR) { dtp->dt_options[option] = val; dtp->dt_ctferr = ctf_errno(fp); return (dt_set_errno(dtp, EDT_CTF)); } return (0); }
static void ctfsrc_object(ctf_id_t id, const char *name) { char tname[MAX_NAMELEN]; if (ctf_type_cname(g_fp, id, tname, sizeof (tname), name) == NULL) { if (ctf_errno(g_fp) != ECTF_NOPARENT) { ctfdump_fatal("type %ld missing name: %s\n", id, ctf_errmsg(ctf_errno(g_fp))); } (void) snprintf(tname, sizeof (tname), "unknown_t %s", name); } (void) printf("extern %s;\n", tname); }
int mdb_ctf_type_iter(const char *object, mdb_ctf_type_f *cb, void *data) { ctf_file_t *fp; mdb_tgt_t *t = mdb.m_target; int ret; type_iter_t ti; if (object == MDB_CTF_SYNTHETIC_ITER) fp = mdb.m_synth; else fp = mdb_tgt_name_to_ctf(t, object); if (fp == NULL) return (-1); ti.ti_cb = cb; ti.ti_arg = data; ti.ti_fp = fp; if ((ret = ctf_type_iter(fp, type_iter_cb, &ti)) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(fp)))); return (ret); }
static int ctfdump_functions_cb(const char *name, ulong_t symidx, ctf_funcinfo_t *ctc, void *arg) { int i; if (ctc->ctc_argc != 0) { ctfdump_fargs_grow(ctc->ctc_argc); if (ctf_func_args(g_fp, symidx, g_nfargc, g_fargc) == CTF_ERR) ctfdump_fatal("failed to get arguments for function " "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); } ctfdump_printf(CTFDUMP_FUNCTIONS, " [%lu] %s (%lu) returns: %u args: (", g_stats.cs_nfuncs, name, symidx, ctc->ctc_return); for (i = 0; i < ctc->ctc_argc; i++) ctfdump_printf(CTFDUMP_FUNCTIONS, "%lu%s", g_fargc[i], i + 1 == ctc->ctc_argc ? "" : ", "); if (ctc->ctc_flags & CTF_FUNC_VARARG) ctfdump_printf(CTFDUMP_FUNCTIONS, "%s...", ctc->ctc_argc == 0 ? "" : ", "); ctfdump_printf(CTFDUMP_FUNCTIONS, ")\n"); g_stats.cs_nfuncs++; g_stats.cs_nfuncargs += ctc->ctc_argc; g_stats.cs_nfuncmax = MAX(ctc->ctc_argc, g_stats.cs_nfuncmax); return (0); }
int mdb_ctf_type_resolve(mdb_ctf_id_t mid, mdb_ctf_id_t *outp) { ctf_id_t id; mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣ if ((id = ctf_type_resolve(idp->mci_fp, idp->mci_id)) == CTF_ERR) { if (outp) mdb_ctf_type_invalidate(outp); return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); } if (ctf_type_kind(idp->mci_fp, id) == CTF_K_FORWARD) { char name[MDB_SYM_NAMLEN]; mdb_ctf_id_t lookup_id; if (ctf_type_name(idp->mci_fp, id, name, sizeof (name)) != NULL && mdb_ctf_lookup_by_name(name, &lookup_id) == 0 && outp != NULL) { *outp = lookup_id; return (0); } } if (outp != NULL) set_ctf_id(outp, idp->mci_fp, id); return (0); }
int mdb_ctf_func_args(const mdb_ctf_funcinfo_t *funcp, uint_t len, mdb_ctf_id_t *argv) { ctf_file_t *fp; ctf_id_t cargv[32]; int i; if (len > (sizeof (cargv) / sizeof (cargv[0]))) return (set_errno(EINVAL)); if (funcp == NULL || argv == NULL) return (set_errno(EINVAL)); fp = mdb_ctf_type_file(funcp->mtf_return); if (ctf_func_args(fp, funcp->mtf_symidx, len, cargv) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(fp)))); for (i = MIN(len, funcp->mtf_argc) - 1; i >= 0; i--) { set_ctf_id(&argv[i], fp, cargv[i]); } return (0); }
int mdb_ctf_lookup_by_symbol(const GElf_Sym *symp, const mdb_syminfo_t *sip, mdb_ctf_id_t *p) { ctf_file_t *fp = NULL; mdb_ctf_impl_t *mcip = (mdb_ctf_impl_t *)p; mdb_tgt_t *t = mdb.m_target; if (mcip == NULL) return (set_errno(EINVAL)); if (symp == NULL || sip == NULL) { mdb_ctf_type_invalidate(p); return (set_errno(EINVAL)); } if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL) { mdb_ctf_type_invalidate(p); return (-1); /* errno is set for us */ } if ((mcip->mci_id = ctf_lookup_by_symbol(fp, sip->sym_id)) == CTF_ERR) { mdb_ctf_type_invalidate(p); return (set_errno(ctf_to_errno(ctf_errno(fp)))); } mcip->mci_fp = fp; return (0); }
int mdb_ctf_type_encoding(mdb_ctf_id_t id, ctf_encoding_t *ep) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; if (ctf_type_encoding(idp->mci_fp, idp->mci_id, ep) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); return (0); }
static void ctfdump_objects(void) { ctfdump_title(CTFDUMP_OBJECTS, "Data Objects"); if (ctf_object_iter(g_fp, ctfdump_objects_cb, NULL) == CTF_ERR) { ctfdump_warn("failed to dump objects: %s\n", ctf_errmsg(ctf_errno(g_fp))); g_exit = 1; } }
static void ctfdump_labels(void) { ctfdump_title(CTFDUMP_LABELS, "Label Table"); if (ctf_label_iter(g_fp, ctfdump_labels_cb, NULL) == CTF_ERR) { ctfdump_warn("failed to dump labels: %s\n", ctf_errmsg(ctf_errno(g_fp))); g_exit = 1; } }
int mdb_ctf_type_kind(mdb_ctf_id_t id) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; int ret; if ((ret = ctf_type_kind(idp->mci_fp, idp->mci_id)) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); return (ret); }
static void ctfdump_functions(void) { ctfdump_title(CTFDUMP_FUNCTIONS, "Functions"); if (ctf_function_iter(g_fp, ctfdump_functions_cb, NULL) == CTF_ERR) { ctfdump_warn("failed to dump functions: %s\n", ctf_errmsg(ctf_errno(g_fp))); g_exit = 1; } }
static void ctfdump_types(void) { ctfdump_title(CTFDUMP_TYPES, "Types"); if (ctf_type_iter(g_fp, B_TRUE, ctfdump_types_cb, NULL) == CTF_ERR) { ctfdump_warn("failed to dump labels: %s\n", ctf_errmsg(ctf_errno(g_fp))); g_exit = 1; } }
static void ctfsrc_refname(ctf_id_t id, char *buf, size_t bufsize) { ctf_id_t ref; if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) { ctfdump_fatal("failed to get reference type for %ld: " "%s\n", id, ctf_errmsg(ctf_errno(g_fp))); } (void) ctf_type_name(g_fp, ref, buf, bufsize); }
static void ctfdump_strings(void) { ulong_t stroff = 0; ctfdump_title(CTFDUMP_STRINGS, "String Table"); if (ctf_string_iter(g_fp, ctfdump_strings_cb, &stroff) == CTF_ERR) { ctfdump_warn("failed to dump strings: %s\n", ctf_errmsg(ctf_errno(g_fp))); g_exit = 1; } }
const char * mdb_ctf_enum_name(mdb_ctf_id_t id, int value) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; const char *ret; /* resolve the type in case there's a forward declaration */ if (mdb_ctf_type_resolve(id, &id) != 0) return (NULL); if ((ret = ctf_enum_name(idp->mci_fp, idp->mci_id, value)) == NULL) (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); return (ret); }
ssize_t mdb_ctf_type_size(mdb_ctf_id_t id) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; ssize_t ret; /* resolve the type in case there's a forward declaration */ if ((ret = mdb_ctf_type_resolve(id, &id)) != 0) return (ret); if ((ret = ctf_type_size(idp->mci_fp, idp->mci_id)) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); return (ret); }
int mdb_ctf_array_info(mdb_ctf_id_t id, mdb_ctf_arinfo_t *arp) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; ctf_arinfo_t car; if (ctf_array_info(idp->mci_fp, idp->mci_id, &car) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); set_ctf_id(&arp->mta_contents, idp->mci_fp, car.ctr_contents); set_ctf_id(&arp->mta_index, idp->mci_fp, car.ctr_index); arp->mta_nelems = car.ctr_nelems; return (0); }
char * mdb_ctf_type_name(mdb_ctf_id_t id, char *buf, size_t len) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; char *ret; if (!mdb_ctf_type_valid(id)) { (void) set_errno(EINVAL); return (NULL); } ret = ctf_type_name(idp->mci_fp, idp->mci_id, buf, len); if (ret == NULL) (void) set_errno(ctf_to_errno(ctf_errno(idp->mci_fp))); return (ret); }
int mdb_ctf_type_reference(mdb_ctf_id_t mid, mdb_ctf_id_t *outp) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)∣ ctf_id_t id; if ((id = ctf_type_reference(idp->mci_fp, idp->mci_id)) == CTF_ERR) { if (outp) mdb_ctf_type_invalidate(outp); return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); } if (outp != NULL) set_ctf_id(outp, idp->mci_fp, id); return (0); }
/*ARGSUSED*/ int mdb_ctf_func_info(const GElf_Sym *symp, const mdb_syminfo_t *sip, mdb_ctf_funcinfo_t *mfp) { ctf_file_t *fp = NULL; ctf_funcinfo_t f; mdb_tgt_t *t = mdb.m_target; char name[MDB_SYM_NAMLEN]; const mdb_map_t *mp; mdb_syminfo_t si; int err; if (symp == NULL || mfp == NULL) return (set_errno(EINVAL)); /* * In case the input symbol came from a merged or private symbol table, * re-lookup the address as a symbol, and then perform a fully scoped * lookup of that symbol name to get the mdb_syminfo_t for its CTF. */ if ((fp = mdb_tgt_addr_to_ctf(t, symp->st_value)) == NULL || (mp = mdb_tgt_addr_to_map(t, symp->st_value)) == NULL || mdb_tgt_lookup_by_addr(t, symp->st_value, MDB_TGT_SYM_FUZZY, name, sizeof (name), NULL, NULL) != 0) return (-1); /* errno is set for us */ if (strchr(name, '`') != NULL) err = mdb_tgt_lookup_by_scope(t, name, NULL, &si); else err = mdb_tgt_lookup_by_name(t, mp->map_name, name, NULL, &si); if (err != 0) return (-1); /* errno is set for us */ if (ctf_func_info(fp, si.sym_id, &f) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(fp)))); set_ctf_id(&mfp->mtf_return, fp, f.ctc_return); mfp->mtf_argc = f.ctc_argc; mfp->mtf_flags = f.ctc_flags; mfp->mtf_symidx = si.sym_id; return (0); }
int dtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp, const dtrace_syminfo_t *sip, dtrace_typeinfo_t *tip) { dt_module_t *dmp; tip->dtt_object = NULL; tip->dtt_ctfp = NULL; tip->dtt_type = CTF_ERR; tip->dtt_flags = 0; if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL) return (dt_set_errno(dtp, EDT_NOMOD)); if (symp->st_shndx == SHN_UNDEF && dmp->dm_extern != NULL) { dt_ident_t *idp = dt_idhash_lookup(dmp->dm_extern, sip->dts_name); if (idp == NULL) return (dt_set_errno(dtp, EDT_NOSYM)); tip->dtt_ctfp = idp->di_ctfp; tip->dtt_type = idp->di_type; } else if (GELF_ST_TYPE(symp->st_info) != STT_FUNC) { if (dt_module_getctf(dtp, dmp) == NULL) return (-1); /* errno is set for us */ tip->dtt_ctfp = dmp->dm_ctfp; tip->dtt_type = ctf_lookup_by_symbol(dmp->dm_ctfp, sip->dts_id); if (tip->dtt_type == CTF_ERR) { dtp->dt_ctferr = ctf_errno(tip->dtt_ctfp); return (dt_set_errno(dtp, EDT_CTF)); } } else { tip->dtt_ctfp = DT_FPTR_CTFP(dtp); tip->dtt_type = DT_FPTR_TYPE(dtp); } tip->dtt_object = dmp->dm_name; return (0); }
int mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p) { ctf_file_t *fp; ctf_id_t id; mdb_module_t *mod; if ((mod = mdb_get_module()) == NULL) return (set_errno(EMDB_CTX)); if ((fp = mod->mod_ctfp) == NULL) return (set_errno(EMDB_NOCTF)); if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(fp)))); set_ctf_id(p, fp, id); return (0); }
int mdb_ctf_type_visit(mdb_ctf_id_t id, mdb_ctf_visit_f *func, void *arg) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; type_visit_t tv; int ret; tv.tv_cb = func; tv.tv_arg = arg; tv.tv_fp = idp->mci_fp; tv.tv_base_offset = 0; tv.tv_base_depth = 0; tv.tv_min_depth = 0; ret = ctf_type_visit(idp->mci_fp, idp->mci_id, type_cb, &tv); if (ret == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); return (ret); }
static void ctfsrc_function(ctf_idname_t *idn) { ctf_funcinfo_t *cfi = &idn->ci_funcinfo; char name[MAX_NAMELEN] = "unknown_t"; (void) ctf_type_name(g_fp, cfi->ctc_return, name, sizeof (name)); (void) printf("extern %s %s(", name, idn->ci_name); if (cfi->ctc_argc != 0) { ctfdump_fargs_grow(cfi->ctc_argc); if (ctf_func_args(g_fp, idn->ci_symidx, g_nfargc, g_fargc) == CTF_ERR) { ctfdump_fatal("failed to get arguments for function " "%s: %s\n", idn->ci_name, ctf_errmsg(ctf_errno(g_fp))); } for (size_t i = 0; i < cfi->ctc_argc; i++) { ctf_id_t aid = g_fargc[i]; name[0] = '\0'; (void) ctf_type_name(g_fp, aid, name, sizeof (name)); (void) printf("%s%s", name, i + 1 == cfi->ctc_argc ? "" : ", "); } } else { if (!(cfi->ctc_flags & CTF_FUNC_VARARG)) (void) printf("void"); } if (cfi->ctc_flags & CTF_FUNC_VARARG) (void) printf("%s...", cfi->ctc_argc == 0 ? "" : ", "); (void) printf(");\n"); }
int mdb_ctf_member_iter(mdb_ctf_id_t id, mdb_ctf_member_f *cb, void *data) { mdb_ctf_impl_t *idp = (mdb_ctf_impl_t *)&id; member_iter_t mi; int ret; /* resolve the type in case there's a forward declaration */ if ((ret = mdb_ctf_type_resolve(id, &id)) != 0) return (ret); mi.mi_cb = cb; mi.mi_arg = data; mi.mi_fp = idp->mci_fp; ret = ctf_member_iter(idp->mci_fp, idp->mci_id, member_iter_cb, &mi); if (ret == CTF_ERR) return (set_errno(ctf_to_errno(ctf_errno(idp->mci_fp)))); return (ret); }
/* * Lookup the dynamic translator type tag for the specified probe argument and * assign the type to the specified node. If the type is not yet defined, add * it to the "D" module's type container as a typedef for an unknown type. */ dt_node_t * dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp) { dtrace_hdl_t *dtp = prp->pr_pvp->pv_hdl; dtrace_typeinfo_t dtt; size_t len; char *tag; len = snprintf(NULL, 0, "__dtrace_%s___%s_arg%u", prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn); tag = alloca(len + 1); (void) snprintf(tag, len + 1, "__dtrace_%s___%s_arg%u", prp->pr_pvp->pv_desc.dtvd_name, prp->pr_name, argn); if (dtrace_lookup_by_type(dtp, DTRACE_OBJ_DDEFS, tag, &dtt) != 0) { dtt.dtt_object = DTRACE_OBJ_DDEFS; dtt.dtt_ctfp = DT_DYN_CTFP(dtp); dtt.dtt_type = ctf_add_typedef(DT_DYN_CTFP(dtp), CTF_ADD_ROOT, tag, DT_DYN_TYPE(dtp)); if (dtt.dtt_type == CTF_ERR || ctf_update(dtt.dtt_ctfp) == CTF_ERR) { xyerror(D_UNKNOWN, "cannot define type %s: %s\n", tag, ctf_errmsg(ctf_errno(dtt.dtt_ctfp))); } } bzero(dnp, sizeof (dt_node_t)); dnp->dn_kind = DT_NODE_TYPE; dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE); dt_node_attr_assign(dnp, _dtrace_defattr); return (dnp); }
int main(int argc, char *argv[]) { int c, fd, err; const char *ufile = NULL, *parent = NULL; g_progname = basename(argv[0]); while ((c = getopt(argc, argv, ":dfhlp:sStu:")) != -1) { switch (c) { case 'd': g_dump |= CTFDUMP_OBJECTS; break; case 'f': g_dump |= CTFDUMP_FUNCTIONS; break; case 'h': g_dump |= CTFDUMP_HEADER; break; case 'l': g_dump |= CTFDUMP_LABELS; break; case 'p': parent = optarg; break; case 's': g_dump |= CTFDUMP_STRINGS; break; case 'S': g_dump |= CTFDUMP_STATS; break; case 't': g_dump |= CTFDUMP_TYPES; break; case 'u': g_dump |= CTFDUMP_OUTPUT; ufile = optarg; break; case '?': ctfdump_usage("Unknown option: -%c\n", optopt); return (2); case ':': ctfdump_usage("Option -%c requires an operand\n", optopt); return (2); } } argc -= optind; argv += optind; /* * Dump all information by default. */ if (g_dump == 0) g_dump = CTFDUMP_DEFAULT; if (argc != 1) { ctfdump_usage("no file to dump\n"); return (2); } if ((fd = open(argv[0], O_RDONLY)) < 0) ctfdump_fatal("failed to open file %s: %s\n", argv[0], strerror(errno)); g_fp = ctf_fdopen(fd, &err); if (g_fp == NULL) ctfdump_fatal("failed to open file %s: %s\n", argv[0], ctf_errmsg(err)); if (parent != NULL) { ctf_file_t *pfp = ctf_open(parent, &err); if (pfp == NULL) ctfdump_fatal("failed to open parent file %s: %s\n", parent, ctf_errmsg(err)); if (ctf_import(g_fp, pfp) != 0) ctfdump_fatal("failed to import parent %s: %s\n", parent, ctf_errmsg(ctf_errno(g_fp))); } /* * If stats is set, we must run through everything exect CTFDUMP_OUTPUT. * We also do CTFDUMP_STATS last as a result. */ if (g_dump & CTFDUMP_HEADER) ctfdump_header(); if (g_dump & (CTFDUMP_LABELS | CTFDUMP_STATS)) ctfdump_labels(); if (g_dump & (CTFDUMP_OBJECTS | CTFDUMP_STATS)) ctfdump_objects(); if (g_dump & (CTFDUMP_FUNCTIONS | CTFDUMP_STATS)) ctfdump_functions(); if (g_dump & (CTFDUMP_TYPES | CTFDUMP_STATS)) ctfdump_types(); if (g_dump & (CTFDUMP_STRINGS | CTFDUMP_STATS)) ctfdump_strings(); if (g_dump & CTFDUMP_STATS) ctfdump_stats(); if (g_dump & CTFDUMP_OUTPUT) ctfdump_output(ufile); return (g_exit); }
static int ctfdump_types_cb(ctf_id_t id, boolean_t root, void *arg) { int kind, i, count; ctf_id_t ref; char name[512], ienc[128]; const char *encn; ctf_funcinfo_t ctc; ctf_arinfo_t ar; ctf_encoding_t cte; ssize_t size; if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) ctfdump_fatal("encountered malformed ctf, type %s does not " "have a kind: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); if (ctf_type_name(g_fp, id, name, sizeof (name)) == NULL) { if (ctf_errno(g_fp) != ECTF_NOPARENT) ctfdump_fatal("type %lu missing name: %s\n", id, ctf_errmsg(ctf_errno(g_fp))); (void) snprintf(name, sizeof (name), "(unknown %s)", ctf_kind_name(g_fp, kind)); } g_stats.cs_ntypes[kind]++; if (root == B_TRUE) ctfdump_printf(CTFDUMP_TYPES, " <%lu> ", id); else ctfdump_printf(CTFDUMP_TYPES, " [%lu] ", id); switch (kind) { case CTF_K_UNKNOWN: break; case CTF_K_INTEGER: if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR) ctfdump_fatal("failed to get encoding information " "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_intenc_name(&cte, ienc, sizeof (ienc)); ctfdump_printf(CTFDUMP_TYPES, "%s encoding=%s offset=%u bits=%u", name, ienc, cte.cte_offset, cte.cte_bits); break; case CTF_K_FLOAT: if (ctf_type_encoding(g_fp, id, &cte) == CTF_ERR) ctfdump_fatal("failed to get encoding information " "for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); if (cte.cte_format < 1 || cte.cte_format > 12) encn = "unknown"; else encn = ctfdump_fpenc[cte.cte_format]; ctfdump_printf(CTFDUMP_TYPES, "%s encoding=%s offset=%u " "bits=%u", name, encn, cte.cte_offset, cte.cte_bits); break; case CTF_K_POINTER: if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) ctfdump_fatal("failed to get reference type for %s: " "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, ref); break; case CTF_K_ARRAY: if (ctf_array_info(g_fp, id, &ar) == CTF_ERR) ctfdump_fatal("failed to get array information for " "%s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_printf(CTFDUMP_TYPES, "%s contents: %lu, index: %lu", name, ar.ctr_contents, ar.ctr_index); break; case CTF_K_FUNCTION: if (ctf_func_info_by_id(g_fp, id, &ctc) == CTF_ERR) ctfdump_fatal("failed to get function info for %s: " "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); if (ctc.ctc_argc > 0) { ctfdump_fargs_grow(ctc.ctc_argc); if (ctf_func_args_by_id(g_fp, id, g_nfargc, g_fargc) == CTF_ERR) ctfdump_fatal("failed to get function " "arguments for %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); } ctfdump_printf(CTFDUMP_TYPES, "%s returns: %lu args: (", name, ctc.ctc_return); for (i = 0; i < ctc.ctc_argc; i++) { ctfdump_printf(CTFDUMP_TYPES, "%lu%s", g_fargc[i], i + 1 == ctc.ctc_argc ? "" : ", "); } if (ctc.ctc_flags & CTF_FUNC_VARARG) ctfdump_printf(CTFDUMP_TYPES, "%s...", ctc.ctc_argc == 0 ? "" : ", "); ctfdump_printf(CTFDUMP_TYPES, ")"); break; case CTF_K_STRUCT: case CTF_K_UNION: size = ctf_type_size(g_fp, id); if (size == CTF_ERR) ctfdump_fatal("failed to get size of %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_printf(CTFDUMP_TYPES, "%s (%d bytes)\n", name, size); count = 0; if (ctf_member_iter(g_fp, id, ctfdump_member_cb, &count) != 0) ctfdump_fatal("failed to iterate members of %s: %s\n", name, ctf_errmsg(ctf_errno(g_fp))); if (kind == CTF_K_STRUCT) { g_stats.cs_nsmembs += count; g_stats.cs_nsmax = MAX(count, g_stats.cs_nsmax); g_stats.cs_structsz += size; g_stats.cs_sszmax = MAX(size, g_stats.cs_sszmax); } else { g_stats.cs_numembs += count; g_stats.cs_numax = MAX(count, g_stats.cs_numax); g_stats.cs_unionsz += size; g_stats.cs_uszmax = MAX(count, g_stats.cs_uszmax); } break; case CTF_K_ENUM: ctfdump_printf(CTFDUMP_TYPES, "%s\n", name); count = 0; if (ctf_enum_iter(g_fp, id, ctfdump_enum_cb, &count) != 0) ctfdump_fatal("failed to iterate enumerators of %s: " "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); g_stats.cs_nemembs += count; g_stats.cs_nemax = MAX(g_stats.cs_nemax, count); break; case CTF_K_FORWARD: ctfdump_printf(CTFDUMP_TYPES, "forward %s\n", name); break; case CTF_K_TYPEDEF: if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) ctfdump_fatal("failed to get reference type for %s: " "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_printf(CTFDUMP_TYPES, "typedef %s refers to %lu", name, ref); break; case CTF_K_VOLATILE: if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) ctfdump_fatal("failed to get reference type for %s: " "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, ref); break; case CTF_K_CONST: if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) ctfdump_fatal("failed to get reference type for %s: " "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, ref); break; case CTF_K_RESTRICT: if ((ref = ctf_type_reference(g_fp, id)) == CTF_ERR) ctfdump_fatal("failed to get reference type for %s: " "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); ctfdump_printf(CTFDUMP_TYPES, "%s refers to %lu", name, ref); break; default: ctfdump_fatal("encountered unknown kind for type %s: %d\n", name, kind); } ctfdump_printf(CTFDUMP_TYPES, "\n"); return (0); }