diff options
author | John Levon <john.levon@joyent.com> | 2018-09-28 17:18:54 +0000 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2018-10-19 15:53:33 +0000 |
commit | 20b880231bb330a968b6ae93b908f6e42057a3e4 (patch) | |
tree | b5e6237062d081a5795a62e9097c7590b1900a51 /usr/src/common | |
parent | 104c53876a87e773ef729efa9419a70fe24933cb (diff) | |
download | illumos-joyent-OS-7275.tar.gz |
OS-7270 ctfconvert doesn't handle DW_AT_specificationOS-7275
OS-7275 ctfdump could generate C-style output
OS-7279 DWARF->CTF enum conversion needs to be careful of sign
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
Diffstat (limited to 'usr/src/common')
-rw-r--r-- | usr/src/common/ctf/ctf_types.c | 143 |
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); +} |