summaryrefslogtreecommitdiff
path: root/usr/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common')
-rw-r--r--usr/src/common/ctf/ctf_types.c143
1 files changed, 133 insertions, 10 deletions
diff --git a/usr/src/common/ctf/ctf_types.c b/usr/src/common/ctf/ctf_types.c
index 2ef4f42d6b..cf0be8d8b5 100644
--- a/usr/src/common/ctf/ctf_types.c
+++ b/usr/src/common/ctf/ctf_types.c
@@ -25,7 +25,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2015, Joyent, Inc.
+ * Copyright 2018 Joyent, Inc.
*/
#include <ctf_impl.h>
@@ -200,13 +200,91 @@ ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
}
/*
- * Lookup the given type ID and print a string name for it into buf. Return
- * the actual number of bytes (not including \0) needed to format the name.
+ * Format an integer type; if a vname is specified, we need to insert it prior
+ * to any bitfield ":24" suffix. This works out far simpler than figuring it
+ * out from scratch.
+ */
+static const char *
+ctf_format_int(ctf_decl_t *cd, const char *vname, const char *qname,
+ const char *name)
+{
+ const char *c;
+
+ if (vname == NULL) {
+ if (qname != NULL)
+ ctf_decl_sprintf(cd, "%s`%s", qname, name);
+ else
+ ctf_decl_sprintf(cd, "%s", name);
+ return (NULL);
+ }
+
+ if ((c = strchr(name, ':')) == NULL) {
+ ctf_decl_sprintf(cd, "%s", name);
+ return (vname);
+ }
+
+ /* "unsigned int mybits:23" */
+ ctf_decl_sprintf(cd, "%.*s %s%s", c - name, name, vname, c);
+ return (NULL);
+}
+
+static void
+ctf_format_func(ctf_file_t *fp, ctf_decl_t *cd,
+ const char *vname, ctf_id_t id, int want_func_args)
+{
+ ctf_funcinfo_t fi;
+ /* We'll presume zone_create() is a bad example. */
+ ctf_id_t args[20];
+
+ ctf_decl_sprintf(cd, "%s(", vname == NULL ? "" : vname);
+
+ if (!want_func_args)
+ goto out;
+
+ if (ctf_func_info_by_id(fp, id, &fi) != 0)
+ goto out;
+
+ if (fi.ctc_argc > ARRAY_SIZE(args))
+ fi.ctc_argc = ARRAY_SIZE(args);
+
+ if (fi.ctc_argc == 0) {
+ ctf_decl_sprintf(cd, "void");
+ goto out;
+ }
+
+ if (ctf_func_args_by_id(fp, id, fi.ctc_argc, args) != 0)
+ goto out;
+
+ for (size_t i = 0; i < fi.ctc_argc; i++) {
+ char aname[512];
+
+ if (ctf_type_name(fp, args[i], aname, sizeof (aname)) == NULL)
+ (void) strlcpy(aname, "unknown_t", sizeof (aname));
+
+ ctf_decl_sprintf(cd, "%s%s", aname,
+ i + 1 == fi.ctc_argc ? "" : ", ");
+ }
+
+ if (fi.ctc_flags & CTF_FUNC_VARARG)
+ ctf_decl_sprintf(cd, "%s...", fi.ctc_argc == 0 ? "" : ", ");
+
+out:
+ ctf_decl_sprintf(cd, ")");
+}
+
+/*
+ * Lookup the given type ID and print a string name for it into buf. Return the
+ * actual number of bytes (not including \0) needed to format the name.
+ *
+ * "vname" is an optional variable name or similar, so array suffix formatting,
+ * bitfields, and functions are C-correct. (This is not perfect, as can be seen
+ * in kiconv_ops_t.)
*/
static ssize_t
ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
- const char *qname)
+ const char *vname, const char *qname)
{
+ int want_func_args = (vname != NULL);
ctf_decl_t cd;
ctf_decl_node_t *cdp;
ctf_decl_prec_t prec, lp, rp;
@@ -258,6 +336,8 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
switch (cdp->cd_kind) {
case CTF_K_INTEGER:
+ vname = ctf_format_int(&cd, vname, qname, name);
+ break;
case CTF_K_FLOAT:
case CTF_K_TYPEDEF:
if (qname != NULL)
@@ -268,10 +348,14 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
ctf_decl_sprintf(&cd, "*");
break;
case CTF_K_ARRAY:
- ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n);
+ ctf_decl_sprintf(&cd, "%s[%u]",
+ vname != NULL ? vname : "", cdp->cd_n);
+ vname = NULL;
break;
case CTF_K_FUNCTION:
- ctf_decl_sprintf(&cd, "()");
+ ctf_format_func(fp, &cd, vname,
+ cdp->cd_type, want_func_args);
+ vname = NULL;
break;
case CTF_K_STRUCT:
case CTF_K_FORWARD:
@@ -306,10 +390,29 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
k = cdp->cd_kind;
}
- if (rp == prec)
+ if (rp == prec) {
+ /*
+ * Peek ahead: if we're going to hit a function,
+ * we want to insert its name now before this closing
+ * bracket.
+ */
+ if (vname != NULL && prec < CTF_PREC_FUNCTION) {
+ cdp = ctf_list_next(
+ &cd.cd_nodes[CTF_PREC_FUNCTION]);
+
+ if (cdp != NULL) {
+ ctf_decl_sprintf(&cd, "%s", vname);
+ vname = NULL;
+ }
+ }
+
ctf_decl_sprintf(&cd, ")");
+ }
}
+ if (vname != NULL)
+ ctf_decl_sprintf(&cd, " %s", vname);
+
if (cd.cd_len >= len)
(void) ctf_set_errno(fp, ECTF_NAMELEN);
@@ -320,7 +423,7 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
ssize_t
ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
{
- return (ctf_type_qlname(fp, type, buf, len, NULL));
+ return (ctf_type_qlname(fp, type, buf, len, NULL, NULL));
}
/*
@@ -330,7 +433,7 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
char *
ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
{
- ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
+ ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, NULL);
return (rv >= 0 && rv < len ? buf : NULL);
}
@@ -338,10 +441,17 @@ char *
ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
const char *qname)
{
- ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
+ ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL, qname);
return (rv >= 0 && rv < len ? buf : NULL);
}
+char *
+ctf_type_cname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
+ const char *cname)
+{
+ ssize_t rv = ctf_type_qlname(fp, type, buf, len, cname, NULL);
+ return (rv >= 0 && rv < len ? buf : NULL);
+}
/*
* Resolve the type down to a base type node, and then return the size
@@ -1185,3 +1295,16 @@ ctf_kind_name(ctf_file_t *fp, int kind)
return ("unknown");
}
}
+
+ctf_id_t
+ctf_max_id(ctf_file_t *fp)
+{
+ int child = (fp->ctf_flags & LCTF_CHILD);
+ return (fp->ctf_typemax + (child ? CTF_CHILD_START : 0));
+}
+
+ulong_t
+ctf_nr_syms(ctf_file_t *fp)
+{
+ return (fp->ctf_nsyms);
+}