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); }
static int ctfdump_labels_cb(const char *name, const ctf_lblinfo_t *li, void *arg) { _NOTE(ARGUNUSED(arg)); ctfdump_printf(CTFDUMP_LABELS, " %5ld %s\n", li->ctb_typeidx, name); return (0); }
static int ctfdump_enum_cb(const char *name, int value, void *arg) { int *count = arg; ctfdump_printf(CTFDUMP_TYPES, "\t%s = %d\n", name, value); *count = *count + 1; return (0); }
static void ctfdump_title(ctfdump_arg_t arg, const char *header) { static const char line[] = "----------------------------------------" "----------------------------------------"; ctfdump_printf(arg, "\n- %s %.*s\n\n", header, (int)78 - strlen(header), line); }
static int ctfdump_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg) { int *count = arg; ctfdump_printf(CTFDUMP_TYPES, "\t%s type=%lu off=%lu\n", member, type, off); *count = *count + 1; return (0); }
static int ctfdump_objects_cb(const char *name, ctf_id_t id, ulong_t symidx, void *arg) { int len; len = snprintf(NULL, 0, " [%u] %u", g_stats.cs_ndata, id); ctfdump_printf(CTFDUMP_OBJECTS, " [%u] %u %*s%s (%u)\n", g_stats.cs_ndata, id, MAX(15 - len, 0), "", name, symidx); g_stats.cs_ndata++; return (0); }
static int ctfdump_strings_cb(const char *s, void *arg) { size_t len = strlen(s) + 1; ulong_t *stroff = arg; ctfdump_printf(CTFDUMP_STRINGS, " [%lu] %s\n", *stroff, *s == '\0' ? "\\0" : s); *stroff = *stroff + len; g_stats.cs_nstrings++; g_stats.cs_strsz += len; g_stats.cs_strmax = MAX(g_stats.cs_strmax, len); return (0); }
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); }
static void ctfdump_stats(void) { int i; ulong_t sum; ctfdump_title(CTFDUMP_STATS, "CTF Statistics"); ctfdump_stat_int("total number of data objects", g_stats.cs_ndata); ctfdump_printf(CTFDUMP_STATS, "\n"); ctfdump_stat_int("total number of functions", g_stats.cs_nfuncs); ctfdump_stat_int("total number of function arguments", g_stats.cs_nfuncargs); ctfdump_stat_int("maximum argument list length", g_stats.cs_nfuncmax); if (g_stats.cs_nfuncs != 0) ctfdump_stat_fp("average argument list length", (float)g_stats.cs_nfuncargs / (float)g_stats.cs_nfuncs); ctfdump_printf(CTFDUMP_STATS, "\n"); sum = 0; for (i = 0; i < CTF_K_MAX; i++) sum += g_stats.cs_ntypes[i]; ctfdump_stat_int("total number of types", sum); ctfdump_stat_int("total number of integers", g_stats.cs_ntypes[CTF_K_INTEGER]); ctfdump_stat_int("total number of floats", g_stats.cs_ntypes[CTF_K_FLOAT]); ctfdump_stat_int("total number of pointers", g_stats.cs_ntypes[CTF_K_POINTER]); ctfdump_stat_int("total number of arrays", g_stats.cs_ntypes[CTF_K_ARRAY]); ctfdump_stat_int("total number of func types", g_stats.cs_ntypes[CTF_K_FUNCTION]); ctfdump_stat_int("total number of structs", g_stats.cs_ntypes[CTF_K_STRUCT]); ctfdump_stat_int("total number of unions", g_stats.cs_ntypes[CTF_K_UNION]); ctfdump_stat_int("total number of enums", g_stats.cs_ntypes[CTF_K_ENUM]); ctfdump_stat_int("total number of forward tags", g_stats.cs_ntypes[CTF_K_FORWARD]); ctfdump_stat_int("total number of typedefs", g_stats.cs_ntypes[CTF_K_TYPEDEF]); ctfdump_stat_int("total number of volatile types", g_stats.cs_ntypes[CTF_K_VOLATILE]); ctfdump_stat_int("total number of const types", g_stats.cs_ntypes[CTF_K_CONST]); ctfdump_stat_int("total number of restrict types", g_stats.cs_ntypes[CTF_K_RESTRICT]); ctfdump_stat_int("total number of unknowns (holes)", g_stats.cs_ntypes[CTF_K_UNKNOWN]); ctfdump_printf(CTFDUMP_STATS, "\n"); ctfdump_stat_int("total number of struct members", g_stats.cs_nsmembs); ctfdump_stat_int("maximum number of struct members", g_stats.cs_nsmax); ctfdump_stat_int("total size of all structs", g_stats.cs_structsz); ctfdump_stat_int("maximum size of a struct", g_stats.cs_sszmax); if (g_stats.cs_ntypes[CTF_K_STRUCT] != 0) { ctfdump_stat_fp("average number of struct members", (float)g_stats.cs_nsmembs / (float)g_stats.cs_ntypes[CTF_K_STRUCT]); ctfdump_stat_fp("average size of a struct", (float)g_stats.cs_structsz / (float)g_stats.cs_ntypes[CTF_K_STRUCT]); } ctfdump_printf(CTFDUMP_STATS, "\n"); ctfdump_stat_int("total number of union members", g_stats.cs_numembs); ctfdump_stat_int("maximum number of union members", g_stats.cs_numax); ctfdump_stat_int("total size of all unions", g_stats.cs_unionsz); ctfdump_stat_int("maximum size of a union", g_stats.cs_uszmax); if (g_stats.cs_ntypes[CTF_K_UNION] != 0) { ctfdump_stat_fp("average number of union members", (float)g_stats.cs_numembs / (float)g_stats.cs_ntypes[CTF_K_UNION]); ctfdump_stat_fp("average size of a union", (float)g_stats.cs_unionsz / (float)g_stats.cs_ntypes[CTF_K_UNION]); } ctfdump_printf(CTFDUMP_STATS, "\n"); ctfdump_stat_int("total number of enum members", g_stats.cs_nemembs); ctfdump_stat_int("maximum number of enum members", g_stats.cs_nemax); if (g_stats.cs_ntypes[CTF_K_ENUM] != 0) { ctfdump_stat_fp("average number of enum members", (float)g_stats.cs_nemembs / (float)g_stats.cs_ntypes[CTF_K_ENUM]); } ctfdump_printf(CTFDUMP_STATS, "\n"); ctfdump_stat_int("total number of strings", g_stats.cs_nstrings); ctfdump_stat_int("bytes of string data", g_stats.cs_strsz); ctfdump_stat_int("maximum string length", g_stats.cs_strmax); if (g_stats.cs_nstrings != 0) ctfdump_stat_fp("average string length", (float)g_stats.cs_strsz / (float)g_stats.cs_nstrings); ctfdump_printf(CTFDUMP_STATS, "\n"); }
static void ctfdump_stat_fp(const char *name, float value) { ctfdump_printf(CTFDUMP_STATS, " %-36s= %.2f\n", name, value); }
static void ctfdump_stat_int(const char *name, ulong_t value) { ctfdump_printf(CTFDUMP_STATS, " %-36s= %lu\n", name, value); }
static void ctfdump_header(void) { const ctf_header_t *hp; const char *parname, *parlabel; ctfdump_title(CTFDUMP_HEADER, "CTF Header"); ctf_dataptr(g_fp, (const void **)&hp, NULL); ctfdump_printf(CTFDUMP_HEADER, " cth_magic = 0x%04x\n", hp->cth_magic); ctfdump_printf(CTFDUMP_HEADER, " cth_version = %u\n", hp->cth_version); ctfdump_printf(CTFDUMP_HEADER, " cth_flags = 0x%02x\n", ctf_flags(g_fp)); parname = ctf_parent_name(g_fp); parlabel = ctf_parent_label(g_fp); ctfdump_printf(CTFDUMP_HEADER, " cth_parlabel = %s\n", parlabel == NULL ? "(anon)" : parlabel); ctfdump_printf(CTFDUMP_HEADER, " cth_parname = %s\n", parname == NULL ? "(anon)" : parname); ctfdump_printf(CTFDUMP_HEADER, " cth_lbloff = %u\n", hp->cth_lbloff); ctfdump_printf(CTFDUMP_HEADER, " cth_objtoff = %u\n", hp->cth_objtoff); ctfdump_printf(CTFDUMP_HEADER, " cth_funcoff = %u\n", hp->cth_funcoff); ctfdump_printf(CTFDUMP_HEADER, " cth_typeoff = %u\n", hp->cth_typeoff); ctfdump_printf(CTFDUMP_HEADER, " cth_stroff = %u\n", hp->cth_stroff); ctfdump_printf(CTFDUMP_HEADER, " cth_strlen = %u\n", hp->cth_strlen); }