예제 #1
0
const char *
mdb_strerror(int err)
{
	static char buf[256];
	const char *str;

	if (err >= EMDB_BASE && (err - EMDB_BASE) < _mdb_nerr)
		str = _mdb_errlist[err - EMDB_BASE];
	else
		str = strerror(err);

	switch (err) {
	case EMDB_PARTIAL:
		(void) mdb_iob_snprintf(buf, sizeof (buf), str,
		    errno_rbytes, errno_nbytes);
		str = buf;
		break;

#ifndef _KMDB
	case EMDB_RTLD_DB:
		if (rd_errstr(errno_rtld_db) != NULL)
			str = rd_errstr(errno_rtld_db);
		break;
#endif

	case EMDB_CTF:
		if (ctf_errmsg(errno_libctf) != NULL)
			str = ctf_errmsg(errno_libctf);
		break;
	}

	return (str ? str : "unknown error");
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
파일: dump.c 프로젝트: apprisi/illumos-gate
int
main(int argc, char **argv)
{
	Elf		*elf;
	ctf_file_t	*ctfp;
	int errp, fd;

	if (ctf_version(CTF_VERSION) == -1)
		errx(1, "mismatched libctf versions\n");

	if (elf_version(EV_CURRENT) == EV_NONE)
		errx(1, "mismatched libelf versions\n");

	if (argc != 2)
		errx(2, "usage: %s <file>\n", __progname);

	if ((ctfp = ctf_open(argv[1], &errp)) == NULL)
		errx(1, "failed to ctf_open file: %s: %s\n", argv[1],
		    ctf_errmsg(errp));

	if ((fd = open(argv[1], O_RDONLY)) == -1)
		errx(1, "could not open %s\n", argv[1]);

	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
		errx(1, "could not interpret ELF from %s\n",
		    argv[1]);

	walk_symtab(elf, argv[1], ctfp, check_sym);

	(void) elf_end(elf);
	(void) close(fd);

	return (0);
}
예제 #5
0
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;
	}
}
예제 #6
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;
	}
}
예제 #7
0
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;
	}
}
예제 #8
0
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;
	}
}
예제 #9
0
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);
}
예제 #10
0
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;
	}
}
예제 #11
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);
}
예제 #12
0
파일: kctl_mod.c 프로젝트: andreiw/polaris
void
kctl_mod_loaded(struct modctl *modp)
{
	int rc;

	mutex_enter(&mod_lock);
	if (modp->mod_mp == NULL) {
		mutex_exit(&mod_lock);
		return;
	}

	if ((rc = kctl_mod_decompress(modp)) != 0) {
		cmn_err(CE_WARN, "failed to decompress CTF data for %s: %s\n",
		    modp->mod_modname, ctf_errmsg(rc));
	}
	mutex_exit(&mod_lock);

	if (!(kmdb_kdi_get_flags() & KMDB_KDI_FL_NOMODS))
		kctl_dmod_autoload(modp->mod_modname);
}
예제 #13
0
const char *
dtrace_errmsg(dtrace_hdl_t *dtp, int error)
{
	const char *str;
	int i;

	if (error == EDT_COMPILER && dtp != NULL && dtp->dt_errmsg[0] != '\0')
		str = dtp->dt_errmsg;
	else if (error == EDT_CTF && dtp != NULL && dtp->dt_ctferr != 0)
		str = ctf_errmsg(dtp->dt_ctferr);
	else if (error >= EDT_BASE && (error - EDT_BASE) < _dt_nerr) {
		for (i = 0; i < _dt_nerr; i++) {
			if (_dt_errlist[i].err == error)
				return (_dt_errlist[i].msg);
		}
		str = NULL;
	} else
		str = strerror(error);

	return (str ? str : "Unknown error");
}
예제 #14
0
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");
}
예제 #15
0
/*
 * 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);
}
예제 #16
0
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, ":cdfhlp:sStu:")) != -1) {
		switch (c) {
		case 'c':
			g_dump |= CTFDUMP_SOURCE;
			break;
		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;

	if ((g_dump & CTFDUMP_SOURCE) && !!(g_dump & ~CTFDUMP_SOURCE)) {
		ctfdump_usage("-c must be specified on its own\n");
		return (2);
	}

	/*
	 * Dump all information except C source 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));

	/*
	 * Check to see if this file needs a parent. If it does not and we were
	 * given one, that should be an error. If it does need one and the
	 * parent is not specified, that is fine, we just won't know how to
	 * find child types. If we are given a parent, check at least that the
	 * labels match.
	 */
	if (ctf_parent_name(g_fp) == NULL) {
		if (parent != NULL)
			ctfdump_fatal("cannot use %s as a parent file, %s is "
			    "not a child\n", parent, argv[0]);
	} else if (parent != NULL) {
		const char *explabel, *label;
		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));

		/*
		 * Before we import the parent into the child, check that the
		 * labels match. While there is also the notion of the parent
		 * name, it's less straightforward to match that. Require that
		 * labels match.
		 */
		explabel = ctf_parent_label(g_fp);
		label = ctf_label_topmost(pfp);
		if (explabel == NULL || label == NULL ||
		    strcmp(explabel, label) != 0) {
			if (label == NULL)
				label = "<missing>";
			if (explabel == NULL)
				explabel = "<missing>";
			ctfdump_fatal("label mismatch between parent %s and "
			    "child %s, parent has %s, child expects %s\n",
			    parent, argv[0], label, explabel);
		}

		if (ctf_import(g_fp, pfp) != 0)
			ctfdump_fatal("failed to import parent %s: %s\n",
			    parent, ctf_errmsg(ctf_errno(g_fp)));
	}

	if (g_dump & CTFDUMP_SOURCE) {
		ctfdump_source();
		return (0);
	}

	/*
	 * 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);
}
예제 #17
0
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);
}
예제 #18
0
static void
ctfsrc_type(ctf_id_t id, const char *name)
{
	char refname[MAX_NAMELEN];
	ctf_id_t ref;
	ssize_t size;
	int kind;

	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)));
	}

	switch (kind) {
	case CTF_K_STRUCT:
	case CTF_K_UNION:
		/*
		 * Delay printing anonymous SOUs; a later typedef will usually
		 * pick them up.
		 */
		if (is_anon_refname(name))
			break;

		if ((size = ctf_type_size(g_fp, id)) == CTF_ERR) {
			ctfdump_fatal("failed to get size of %s: %s\n", name,
			    ctf_errmsg(ctf_errno(g_fp)));
		}

		(void) printf("%s { /* 0x%x bytes */\n", name, size);

		if (ctf_member_iter(g_fp, id, ctfsrc_member_cb, NULL) != 0) {
			ctfdump_fatal("failed to iterate members of %s: %s\n",
			    name, ctf_errmsg(ctf_errno(g_fp)));
		}

		(void) printf("};\n\n");
		break;
	case CTF_K_ENUM:
		/*
		 * This will throw away any anon enum that isn't followed by a
		 * typedef...
		 */
		if (is_anon_refname(name))
			break;

		(void) printf("%s {\n", name);

		if (ctf_enum_iter(g_fp, id, ctfsrc_enum_cb, NULL) != 0) {
			ctfdump_fatal("failed to iterate enumerators of %s: "
			    "%s\n", name, ctf_errmsg(ctf_errno(g_fp)));
		}

		(void) printf("};\n\n");
		break;
	case CTF_K_TYPEDEF:
		ctfsrc_refname(id, refname, sizeof (refname));

		if (!is_anon_refname(refname)) {
			(void) ctf_type_cname(g_fp,
			    ctf_type_reference(g_fp, id), refname,
			    sizeof (refname), name);

			(void) printf("typedef %s;\n\n", refname);
			break;
		}

		ref = ctf_type_reference(g_fp, id);

		if (ctf_type_kind(g_fp, ref) == CTF_K_ENUM) {
			(void) printf("typedef enum {\n");

			if (ctf_enum_iter(g_fp, ref,
			    ctfsrc_enum_cb, NULL) != 0) {
				ctfdump_fatal("failed to iterate enumerators "
				    "of %s: %s\n", refname,
				    ctf_errmsg(ctf_errno(g_fp)));
			}

			(void) printf("} %s;\n\n", name);
		} else {
			if ((size = ctf_type_size(g_fp, ref)) == CTF_ERR) {
				ctfdump_fatal("failed to get size of %s: %s\n",
				    refname, ctf_errmsg(ctf_errno(g_fp)));
			}

			(void) printf("typedef %s{ /* 0x%zx bytes */\n",
			    refname, size);

			if (ctf_member_iter(g_fp, ref,
			    ctfsrc_member_cb, NULL) != 0) {
				ctfdump_fatal("failed to iterate members "
				    "of %s: %s\n", refname,
				    ctf_errmsg(ctf_errno(g_fp)));
			}

			(void) printf("} %s;\n\n", name);
		}

		break;
	case CTF_K_FORWARD:
		(void) printf("%s;\n\n", name);
		break;
	case CTF_K_UNKNOWN:
	case CTF_K_INTEGER:
	case CTF_K_FLOAT:
	case CTF_K_POINTER:
	case CTF_K_ARRAY:
	case CTF_K_FUNCTION:
	case CTF_K_VOLATILE:
	case CTF_K_CONST:
	case CTF_K_RESTRICT:
		break;
	default:
		ctfdump_fatal("encountered unknown kind for type %s: %d\n",
		    name, kind);
		break;
	}
}
예제 #19
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);
}
예제 #20
0
static void
ctfdump_source(void)
{
	ulong_t nr_syms = ctf_nr_syms(g_fp);
	ctf_id_t max_id = ctf_max_id(g_fp);
	size_t count = 0;

	(void) printf("/* Types */\n\n");

	if ((idnames = calloc(max_id + 1, sizeof (idnames[0]))) == NULL) {
		ctfdump_fatal("failed to alloc idnames: %s\n",
		    strerror(errno));
	}

	if (ctf_type_iter(g_fp, B_FALSE, ctfsrc_collect_types_cb,
	    idnames) == CTF_ERR) {
		warnx("failed to collect types: %s",
		    ctf_errmsg(ctf_errno(g_fp)));
		g_exit = 1;
	}

	qsort(idnames, max_id, sizeof (ctf_idname_t), idname_compare);

	for (size_t i = 0; i < max_id; i++) {
		if (idnames[i].ci_id != 0)
			ctfsrc_type(idnames[i].ci_id, idnames[i].ci_name);
	}

	free(idnames);

	(void) printf("\n\n/* Data Objects */\n\n");

	if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) {
		ctfdump_fatal("failed to alloc idnames: %s\n",
		    strerror(errno));
	}

	if (ctf_object_iter(g_fp, ctfsrc_collect_objects_cb,
	    &count) == CTF_ERR) {
		warnx("failed to collect objects: %s",
		    ctf_errmsg(ctf_errno(g_fp)));
		g_exit = 1;
	}

	qsort(idnames, count, sizeof (ctf_idname_t), idname_compare);

	for (size_t i = 0; i < count; i++)
		ctfsrc_object(idnames[i].ci_id, idnames[i].ci_name);

	free(idnames);

	(void) printf("\n\n/* Functions */\n\n");

	if ((idnames = calloc(nr_syms, sizeof (idnames[0]))) == NULL) {
		ctfdump_fatal("failed to alloc idnames: %s\n",
		    strerror(errno));
	}

	count = 0;

	if (ctf_function_iter(g_fp, ctfsrc_collect_functions_cb,
	    &count) == CTF_ERR) {
		warnx("failed to collect functions: %s",
		    ctf_errmsg(ctf_errno(g_fp)));
		g_exit = 1;
	}

	qsort(idnames, count, sizeof (ctf_idname_t), idname_compare);

	for (size_t i = 0; i < count; i++)
		ctfsrc_function(&idnames[i]);

	free(idnames);
}
예제 #21
0
/*
 * Begin a macro.
 *
 * Once we figure out the type of the thing that we're supposed to dump (struct,
 * union, or enum), we select the proper type-specific ops-vector for dumping.
 */
static int
fth_section_init(char *fullname)
{
	ctf_id_t ltid = 0, tid;
	char *curtype, *lpart, *part, *npart;
	int lkind = 0, kind;

	curtype = xstrdup(fullname);
	lpart = NULL;
	part = strtok(fullname, ".");

	/*
	 * First figure out what sort of type we're looking at.  Life would be
	 * simple if we were only going to get type names, but it's not - we
	 * could also get `type.member'.  In that case, we need to figure out
	 * (and dump) the type of `member' instead.
	 */
	for (;;) {
		if (lpart == NULL) {
			/* First part - the struct name */
			if ((tid = find_type(part)) == CTF_ERR ||
			    (tid = ctf_type_resolve(ctf, tid)) == CTF_ERR ||
			    (kind = ctf_type_kind(ctf, tid)) == CTF_ERR) {
				free(curtype);
				return (parse_warn("Couldn't find %s: %s",
				    part, ctf_errmsg(ctf_errno(ctf))));
			}
		} else {
			/* Second (or more) part - the member name */
			if (lkind != CTF_K_STRUCT && lkind != CTF_K_UNION) {
				free(curtype);
				return (parse_warn("%s isn't a struct/union",
				    lpart));
			}

			if ((tid = find_member(ltid, part)) <= 0) {
				free(curtype);
				return (parse_warn("%s isn't a member of %s",
				    part, lpart));
			}

			if ((kind = ctf_type_kind(ctf, tid)) == CTF_ERR) {
				free(curtype);
				return (parse_warn("Can't get kind for %s",
				    part));
			}
		}

		/*
		 * Stop if there aren't any more parts.  We use `npart' here
		 * because we don't want to clobber part - we need it later.
		 */
		if ((npart = strtok(NULL, ".")) == NULL)
			break;

		lpart = part;
		ltid = tid;
		lkind = kind;

		part = npart;
	}

	/*
	 * Pick the right ops vector for dumping.
	 */
	switch (kind) {
	case CTF_K_STRUCT:
	case CTF_K_UNION:
		fth_type_ops = &fth_struct_ops;
		break;

	case CTF_K_ENUM:
		fth_type_ops = &fth_enum_ops;
		break;

	default:
		fth_type_ops = &fth_null_ops;
		free(curtype);
		return (parse_warn("%s isn't a struct, union, or enum", part));
	}

	fth_curtype = curtype;

	return (fth_type_ops->fto_header(tid));
}