Print this page
10823 should ignore DW_TAG_subprogram with DW_AT_declaration tags
10824 GCC7-derived CTF can double qualifiers on arrays
10825 ctfdump -c drops last type
10826 ctfdump -c goes off the rails with a missing parent
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
@@ -8,11 +8,11 @@
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
* Dump information about CTF containers.
*/
@@ -683,21 +683,21 @@
* - doubly-pointed-to functions are wrong (e.g. in kiconv_ops_t)
* - anon unions declared within SOUs aren't expanded
* - function arguments aren't expanded recursively
*/
-static void
+static const char *
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);
+ return (ctf_type_name(g_fp, ref, buf, bufsize));
}
static int
ctfsrc_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg)
{
@@ -716,24 +716,24 @@
/*
* 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",
+ printf("\t%s; /* offset: %lu bytes (%lu bits) */\n",
name, off / NBBY, off);
} else {
- (void) printf("\t%s; /* offset: %lu bytes */\n",
+ printf("\t%s; /* offset: %lu bytes */\n",
name, off / NBBY);
}
return (0);
}
static int
ctfsrc_enum_cb(const char *name, int value, void *arg)
{
_NOTE(ARGUNUSED(arg));
- (void) printf("\t%s = %d,\n", name, value);
+ printf("\t%s = %d,\n", name, value);
return (0);
}
static int
is_anon_refname(const char *refname)
@@ -754,11 +754,11 @@
}
static void
ctfsrc_type(ctf_id_t id, const char *name)
{
- char refname[MAX_NAMELEN];
+ char refname[MAX_NAMELEN] = "unknown_t";
ctf_id_t ref;
ssize_t size;
int kind;
if ((kind = ctf_type_kind(g_fp, id)) == CTF_ERR) {
@@ -779,83 +779,90 @@
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);
+ 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");
+ 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);
+ 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");
+ printf("};\n\n");
break;
case CTF_K_TYPEDEF:
- ctfsrc_refname(id, refname, sizeof (refname));
+ /*
+ * If this fails, it's probably because the referent type is in
+ * a parent container that was not supplied via -p.
+ */
+ if (ctfsrc_refname(id, refname, sizeof (refname)) == NULL) {
+ printf("typedef %s %s;\n\n", refname, name);
+ break;
+ }
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);
+ 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");
+ 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);
+ 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",
+ 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);
+ printf("} %s;\n\n", name);
}
break;
case CTF_K_FORWARD:
- (void) printf("%s;\n\n", name);
+ printf("%s;\n\n", name);
break;
case CTF_K_UNKNOWN:
case CTF_K_INTEGER:
case CTF_K_FLOAT:
case CTF_K_POINTER:
@@ -901,11 +908,11 @@
ctf_errmsg(ctf_errno(g_fp)));
}
(void) snprintf(tname, sizeof (tname), "unknown_t %s", name);
}
- (void) printf("extern %s;\n", tname);
+ printf("extern %s;\n", tname);
}
static int
ctfsrc_collect_functions_cb(const char *name, ulong_t symidx,
ctf_funcinfo_t *ctc, void *arg)
@@ -927,11 +934,11 @@
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);
+ 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) {
@@ -941,26 +948,26 @@
}
for (size_t i = 0; i < cfi->ctc_argc; i++) {
ctf_id_t aid = g_fargc[i];
- name[0] = '\0';
+ (void) strlcpy(name, "unknown_t", sizeof (name));
(void) ctf_type_name(g_fp, aid, name, sizeof (name));
- (void) printf("%s%s", name,
+ printf("%s%s", name,
i + 1 == cfi->ctc_argc ? "" : ", ");
}
} else {
if (!(cfi->ctc_flags & CTF_FUNC_VARARG))
- (void) printf("void");
+ printf("void");
}
if (cfi->ctc_flags & CTF_FUNC_VARARG)
- (void) printf("%s...", cfi->ctc_argc == 0 ? "" : ", ");
+ printf("%s...", cfi->ctc_argc == 0 ? "" : ", ");
- (void) printf(");\n");
+ printf(");\n");
}
static int
idname_compare(const void *lhs, const void *rhs)
{
@@ -973,34 +980,43 @@
{
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");
+ printf("/* Types */\n\n");
if ((idnames = calloc(max_id + 1, sizeof (idnames[0]))) == NULL) {
ctfdump_fatal("failed to alloc idnames: %s\n",
strerror(errno));
}
+ /*
+ * Prep for any unknown types (most likely, they exist in the parent,
+ * but we weren't given the -p option).
+ */
+ for (size_t i = 0; i <= max_id; i++) {
+ (void) strlcpy(idnames[i].ci_name, "unknown_t",
+ sizeof (idnames[i].ci_name));
+ }
+
if (ctf_type_iter(g_fp, B_TRUE, 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++) {
+ 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");
+ 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));
}
@@ -1017,11 +1033,11 @@
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");
+ 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));
}
@@ -1194,11 +1210,21 @@
}
if (ctf_import(g_fp, pfp) != 0)
ctfdump_fatal("failed to import parent %s: %s\n",
parent, ctf_errmsg(ctf_errno(g_fp)));
+ } else {
+ if (g_dump & CTFDUMP_SOURCE) {
+ printf("/* Warning: parent \"%s\" not supplied: many "
+ "types will be unknown. */\n\n",
+ ctf_parent_name(g_fp));
+ } else {
+ fprintf(stderr, "warning: parent \"%s\" not supplied: "
+ "many types will be unknown\n\n",
+ ctf_parent_name(g_fp));
}
+ }
if (g_dump & CTFDUMP_SOURCE) {
ctfdump_source();
return (0);
}