summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@joyent.com>2019-04-11 14:03:27 +0000
committerJohn Levon <john.levon@joyent.com>2019-05-03 02:15:58 -0700
commit6ef284f1d464c08bc420048a0b211080cb9fe009 (patch)
tree899285312544e2f8939f8e248283cbd4ae45e6d2
parent59d77acb140ef81a3e7784b472f41ff409b72114 (diff)
downloadillumos-joyent-6ef284f1d464c08bc420048a0b211080cb9fe009.tar.gz
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: Gordon Ross <gwr@nexenta.com>
-rw-r--r--usr/src/cmd/ctfdump/ctfdump.c84
-rw-r--r--usr/src/common/ctf/ctf_impl.h5
-rw-r--r--usr/src/common/ctf/ctf_lookup.c51
-rw-r--r--usr/src/lib/libctf/common/ctf_dwarf.c109
-rw-r--r--usr/src/pkg/manifests/system-test-utiltest.mf70
-rw-r--r--usr/src/test/util-tests/tests/ctf/Makefile6
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-array.c4
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-common.c83
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-common.h4
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-enum.c4
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-forward.c4
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-qualifiers.c318
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-reference.c67
-rw-r--r--usr/src/test/util-tests/tests/ctf/check-sou.c45
-rw-r--r--usr/src/test/util-tests/tests/ctf/test-merge-weak/test-merge-weak.c4
-rwxr-xr-xusr/src/test/util-tests/tests/ctf/test-qualifiers.c42
16 files changed, 801 insertions, 99 deletions
diff --git a/usr/src/cmd/ctfdump/ctfdump.c b/usr/src/cmd/ctfdump/ctfdump.c
index ec879fcc06..b77ef56a24 100644
--- a/usr/src/cmd/ctfdump/ctfdump.c
+++ b/usr/src/cmd/ctfdump/ctfdump.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -685,7 +685,7 @@ ctfdump_types(void)
* - 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;
@@ -695,7 +695,7 @@ ctfsrc_refname(ctf_id_t id, char *buf, size_t bufsize)
"%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
@@ -718,10 +718,10 @@ ctfsrc_member_cb(const char *member, ctf_id_t type, ulong_t off, void *arg)
* 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);
@@ -731,7 +731,7 @@ 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);
}
@@ -756,7 +756,7 @@ ctfsrc_collect_types_cb(ctf_id_t id, boolean_t root, void *arg)
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;
@@ -781,14 +781,14 @@ ctfsrc_type(ctf_id_t id, const char *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:
/*
@@ -798,31 +798,38 @@ ctfsrc_type(ctf_id_t id, const char *name)
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) {
@@ -831,14 +838,14 @@ ctfsrc_type(ctf_id_t id, const char *name)
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,
@@ -848,12 +855,12 @@ ctfsrc_type(ctf_id_t id, const char *name)
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:
@@ -903,7 +910,7 @@ ctfsrc_object(ctf_id_t id, const char *name)
(void) snprintf(tname, sizeof (tname), "unknown_t %s", name);
}
- (void) printf("extern %s;\n", tname);
+ printf("extern %s;\n", tname);
}
static int
@@ -929,7 +936,7 @@ ctfsrc_function(ctf_idname_t *idn)
(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);
@@ -943,22 +950,22 @@ ctfsrc_function(ctf_idname_t *idn)
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
@@ -975,13 +982,22 @@ ctfdump_source(void)
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",
@@ -991,14 +1007,14 @@ ctfdump_source(void)
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",
@@ -1019,7 +1035,7 @@ ctfdump_source(void)
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",
@@ -1196,6 +1212,16 @@ main(int argc, char *argv[])
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) {
diff --git a/usr/src/common/ctf/ctf_impl.h b/usr/src/common/ctf/ctf_impl.h
index 93a85a8b4f..b82fb7e36e 100644
--- a/usr/src/common/ctf/ctf_impl.h
+++ b/usr/src/common/ctf/ctf_impl.h
@@ -25,7 +25,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2015, Joyent, Inc. All rights reserved.
+ * Copyright 2019, Joyent, Inc.
*/
#ifndef _CTF_IMPL_H
@@ -315,6 +315,9 @@ extern ctf_id_t ctf_add_reftype(ctf_file_t *, uint_t, const char *, ctf_id_t,
extern boolean_t ctf_sym_valid(uintptr_t, int, uint16_t, uint64_t,
uint32_t);
+extern const ctf_type_t *ctf_dyn_lookup_by_id(ctf_file_t *, ctf_id_t);
+extern int ctf_dyn_array_info(ctf_file_t *, ctf_id_t, ctf_arinfo_t *);
+
extern const char _CTF_SECTION[]; /* name of CTF ELF section */
extern const char _CTF_NULLSTR[]; /* empty string */
diff --git a/usr/src/common/ctf/ctf_lookup.c b/usr/src/common/ctf/ctf_lookup.c
index f8fa724355..05aa54d6cb 100644
--- a/usr/src/common/ctf/ctf_lookup.c
+++ b/usr/src/common/ctf/ctf_lookup.c
@@ -25,7 +25,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright 2019, Joyent, Inc.
+ */
#include <sys/sysmacros.h>
#include <ctf_impl.h>
@@ -311,3 +313,50 @@ ctf_func_args(ctf_file_t *fp, ulong_t symidx, uint_t argc, ctf_id_t *argv)
return (0);
}
+
+/*
+ * Unlike the normal lookup routines, ctf_dyn_*() variants consult both the
+ * processed CTF contents of a ctf_file_t as well as the dynamic types in the
+ * dtdef list.
+ */
+
+const ctf_type_t *
+ctf_dyn_lookup_by_id(ctf_file_t *fp, ctf_id_t id)
+{
+ ctf_file_t **fpp = &fp;
+ const ctf_type_t *t;
+ ctf_dtdef_t *dtd;
+
+ if ((t = ctf_lookup_by_id(fpp, id)) != NULL)
+ return (t);
+
+ if ((dtd = ctf_dtd_lookup(fp, id)) == NULL)
+ return (NULL);
+
+ return (&dtd->dtd_data);
+}
+
+int
+ctf_dyn_array_info(ctf_file_t *infp, ctf_id_t id, ctf_arinfo_t *arinfop)
+{
+ ctf_file_t *fp = infp;
+ const ctf_type_t *t;
+ ctf_dtdef_t *dtd;
+
+ if ((t = ctf_lookup_by_id(&fp, id)) != NULL) {
+
+ if (LCTF_INFO_KIND(fp, t->ctt_info) != CTF_K_ARRAY)
+ return (ctf_set_errno(infp, ECTF_NOTARRAY));
+
+ return (ctf_array_info(fp, id, arinfop));
+ }
+
+ if ((dtd = ctf_dtd_lookup(fp, id)) == NULL)
+ return (ctf_set_errno(infp, ENOENT));
+
+ if (LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
+ return (ctf_set_errno(infp, ECTF_NOTARRAY));
+
+ bcopy(&dtd->dtd_u.dtu_arr, arinfop, sizeof (*arinfop));
+ return (0);
+}
diff --git a/usr/src/lib/libctf/common/ctf_dwarf.c b/usr/src/lib/libctf/common/ctf_dwarf.c
index aa55127d26..3f57ef6704 100644
--- a/usr/src/lib/libctf/common/ctf_dwarf.c
+++ b/usr/src/lib/libctf/common/ctf_dwarf.c
@@ -28,7 +28,7 @@
*/
/*
- * Copyright 2019 Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -1485,6 +1485,75 @@ ctf_dwarf_create_array(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot)
return (ctf_dwmap_add(cup, *idp, die, B_FALSE));
}
+/*
+ * Given "const int const_array3[11]", GCC7 at least will create a DIE tree of
+ * DW_TAG_const_type:DW_TAG_array_type:DW_Tag_const_type:<member_type>.
+ *
+ * Given C's syntax, this renders out as "const const int const_array3[11]". To
+ * get closer to round-tripping (and make the unit tests work), we'll peek for
+ * this case, and avoid adding the extraneous qualifier if we see that the
+ * underlying array referent already has the same qualifier.
+ *
+ * This is unfortunately less trivial than it could be: this issue applies to
+ * qualifier sets like "const volatile", as well as multi-dimensional arrays, so
+ * we need to descend down those.
+ *
+ * Returns CTF_ERR on error, or a boolean value otherwise.
+ */
+static int
+needed_array_qualifier(ctf_cu_t *cup, int kind, ctf_id_t ref_id)
+{
+ const ctf_type_t *t;
+ ctf_arinfo_t arinfo;
+ int akind;
+
+ if (kind != CTF_K_CONST && kind != CTF_K_VOLATILE &&
+ kind != CTF_K_RESTRICT)
+ return (1);
+
+ if ((t = ctf_dyn_lookup_by_id(cup->cu_ctfp, ref_id)) == NULL)
+ return (CTF_ERR);
+
+ if (LCTF_INFO_KIND(cup->cu_ctfp, t->ctt_info) != CTF_K_ARRAY)
+ return (1);
+
+ if (ctf_dyn_array_info(cup->cu_ctfp, ref_id, &arinfo) != 0)
+ return (CTF_ERR);
+
+ ctf_id_t id = arinfo.ctr_contents;
+
+ for (;;) {
+ if ((t = ctf_dyn_lookup_by_id(cup->cu_ctfp, id)) == NULL)
+ return (CTF_ERR);
+
+ akind = LCTF_INFO_KIND(cup->cu_ctfp, t->ctt_info);
+
+ if (akind == kind)
+ break;
+
+ if (akind == CTF_K_ARRAY) {
+ if (ctf_dyn_array_info(cup->cu_ctfp,
+ id, &arinfo) != 0)
+ return (CTF_ERR);
+ id = arinfo.ctr_contents;
+ continue;
+ }
+
+ if (akind != CTF_K_CONST && akind != CTF_K_VOLATILE &&
+ akind != CTF_K_RESTRICT)
+ break;
+
+ id = t->ctt_type;
+ }
+
+ if (kind == akind) {
+ ctf_dprintf("ignoring extraneous %s qualifier for array %d\n",
+ ctf_kind_name(cup->cu_ctfp, kind), ref_id);
+ }
+
+ return (kind != akind);
+}
+
static int
ctf_dwarf_create_reference(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp,
int kind, int isroot)
@@ -1524,6 +1593,17 @@ ctf_dwarf_create_reference(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp,
}
}
+ if ((ret = needed_array_qualifier(cup, kind, id)) <= 0) {
+ if (ret != 0) {
+ ret = (ctf_errno(cup->cu_ctfp));
+ } else {
+ *idp = id;
+ }
+
+ ctf_free(name, namelen);
+ return (ret);
+ }
+
if ((*idp = ctf_add_reftype(cup->cu_ctfp, isroot, name, id, kind)) ==
CTF_ERR) {
ctf_free(name, namelen);
@@ -1821,7 +1901,7 @@ ctf_dwarf_function_count(ctf_cu_t *cup, Dwarf_Die die, ctf_funcinfo_t *fip,
return (ret);
/*
- * We have to check for a varargs type decleration. This will
+ * We have to check for a varargs type declaration. This will
* happen in one of two ways. If we have a function pointer
* type, then it'll be done with a tag of type
* DW_TAG_unspecified_parameters. However, it only means we have
@@ -1906,10 +1986,11 @@ ctf_dwarf_convert_fargs(ctf_cu_t *cup, Dwarf_Die die, ctf_funcinfo_t *fip,
static int
ctf_dwarf_convert_function(ctf_cu_t *cup, Dwarf_Die die)
{
- int ret;
- char *name;
ctf_dwfunc_t *cdf;
Dwarf_Die tdie;
+ Dwarf_Bool b;
+ char *name;
+ int ret;
/*
* Functions that don't have a name are generally functions that have
@@ -1923,7 +2004,25 @@ ctf_dwarf_convert_function(ctf_cu_t *cup, Dwarf_Die die)
return (ret);
}
- ctf_dprintf("beginning work on function %s\n", name);
+ ctf_dprintf("beginning work on function %s (die %llx)\n",
+ name, ctf_die_offset(die));
+
+ if ((ret = ctf_dwarf_boolean(cup, die, DW_AT_declaration, &b)) != 0) {
+ if (ret != ENOENT)
+ return (ret);
+ } else if (b != 0) {
+ /*
+ * GCC7 at least creates empty DW_AT_declarations for functions
+ * defined in headers. As they lack details on the function
+ * prototype, we need to ignore them. If we later actually
+ * see the relevant function's definition, we will see another
+ * DW_TAG_subprogram that is more complete.
+ */
+ ctf_dprintf("ignoring declaration of function %s (die %llx)\n",
+ name, ctf_die_offset(die));
+ return (0);
+ }
+
if ((cdf = ctf_alloc(sizeof (ctf_dwfunc_t))) == NULL) {
ctf_free(name, strlen(name) + 1);
return (ENOMEM);
diff --git a/usr/src/pkg/manifests/system-test-utiltest.mf b/usr/src/pkg/manifests/system-test-utiltest.mf
index e6bbc9b388..3010f4ea87 100644
--- a/usr/src/pkg/manifests/system-test-utiltest.mf
+++ b/usr/src/pkg/manifests/system-test-utiltest.mf
@@ -13,7 +13,7 @@
# Copyright (c) 2012 by Delphix. All rights reserved.
# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
-# Copyright 2017 Joyent, Inc.
+# Copyright 2019, Joyent, Inc.
# Copyright 2017 Jason King.
#
@@ -27,6 +27,12 @@ dir path=opt/util-tests
dir path=opt/util-tests/bin
dir path=opt/util-tests/runfiles
dir path=opt/util-tests/tests
+dir path=opt/util-tests/tests/ctf
+dir path=opt/util-tests/tests/ctf/test-merge-dedup
+dir path=opt/util-tests/tests/ctf/test-merge-forward
+dir path=opt/util-tests/tests/ctf/test-merge-reduction
+dir path=opt/util-tests/tests/ctf/test-merge-static
+dir path=opt/util-tests/tests/ctf/test-merge-weak
dir path=opt/util-tests/tests/demangle
dir path=opt/util-tests/tests/dis
dir path=opt/util-tests/tests/dis/i386
@@ -43,6 +49,68 @@ file path=opt/util-tests/bin/utiltest mode=0555
file path=opt/util-tests/runfiles/default.run mode=0444
file path=opt/util-tests/tests/allowed-ips mode=0555
file path=opt/util-tests/tests/chown_test mode=0555
+file path=opt/util-tests/tests/ctf/Makefile.ctftest.com mode=0555
+file path=opt/util-tests/tests/ctf/check-array mode=0555
+file path=opt/util-tests/tests/ctf/check-enum mode=0555
+file path=opt/util-tests/tests/ctf/check-float-32 mode=0555
+file path=opt/util-tests/tests/ctf/check-float-64 mode=0555
+file path=opt/util-tests/tests/ctf/check-forward-32 mode=0555
+file path=opt/util-tests/tests/ctf/check-forward-64 mode=0555
+file path=opt/util-tests/tests/ctf/check-function mode=0555
+file path=opt/util-tests/tests/ctf/check-int-32 mode=0555
+file path=opt/util-tests/tests/ctf/check-int-64 mode=0555
+file path=opt/util-tests/tests/ctf/check-merge-dedup mode=0555
+file path=opt/util-tests/tests/ctf/check-merge-forward-32 mode=0555
+file path=opt/util-tests/tests/ctf/check-merge-forward-64 mode=0555
+file path=opt/util-tests/tests/ctf/check-merge-reduction mode=0555
+file path=opt/util-tests/tests/ctf/check-merge-static mode=0555
+file path=opt/util-tests/tests/ctf/check-merge-weak mode=0555
+file path=opt/util-tests/tests/ctf/check-qualifiers mode=0555
+file path=opt/util-tests/tests/ctf/check-reference mode=0555
+file path=opt/util-tests/tests/ctf/check-sou-32 mode=0555
+file path=opt/util-tests/tests/ctf/check-sou-64 mode=0555
+file path=opt/util-tests/tests/ctf/check-weak mode=0555
+file path=opt/util-tests/tests/ctf/ctftest mode=0555
+file path=opt/util-tests/tests/ctf/ctftest-convert-no-dwarf mode=0555
+file path=opt/util-tests/tests/ctf/ctftest-convert-non-c mode=0555
+file path=opt/util-tests/tests/ctf/ctftest-merge-no-ctf mode=0555
+file path=opt/util-tests/tests/ctf/precheck mode=0555
+file path=opt/util-tests/tests/ctf/test-array.c mode=0555
+file path=opt/util-tests/tests/ctf/test-enum.c mode=0555
+file path=opt/util-tests/tests/ctf/test-float.c mode=0555
+file path=opt/util-tests/tests/ctf/test-forward.c mode=0555
+file path=opt/util-tests/tests/ctf/test-function.c mode=0555
+file path=opt/util-tests/tests/ctf/test-int.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-dedup/Makefile.ctftest mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-dedup/test-merge-1.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-dedup/test-merge-2.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-dedup/test-merge-3.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-dedup/test-merge-dedup.c \
+ mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-forward/Makefile.ctftest \
+ mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-forward/test-impl.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-forward/test-merge.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-reduction/Makefile.ctftest \
+ mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-reduction/mapfile-vers mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-reduction/test-global.c \
+ mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-reduction/test-scoped.c \
+ mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-static/Makefile.ctftest \
+ mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-static/test-a.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-static/test-b.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-static/test-c.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-static/test-d.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-static/test-main.c mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-weak/Makefile.ctftest mode=0555
+file path=opt/util-tests/tests/ctf/test-merge-weak/test-merge-weak.c mode=0555
+file path=opt/util-tests/tests/ctf/test-qualifiers.c mode=0555
+file path=opt/util-tests/tests/ctf/test-reference.c mode=0555
+file path=opt/util-tests/tests/ctf/test-sou.c mode=0555
+file path=opt/util-tests/tests/ctf/test-weak.c mode=0555
file path=opt/util-tests/tests/date_test mode=0555
file path=opt/util-tests/tests/demangle/afl-fast mode=0555
file path=opt/util-tests/tests/demangle/gcc-libstdc++ mode=0555
diff --git a/usr/src/test/util-tests/tests/ctf/Makefile b/usr/src/test/util-tests/tests/ctf/Makefile
index 9a65e51e90..1a87c3d835 100644
--- a/usr/src/test/util-tests/tests/ctf/Makefile
+++ b/usr/src/test/util-tests/tests/ctf/Makefile
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2019, Joyent, Inc.
+# Copyright 2019, Joyent, Inc.
#
include $(SRC)/Makefile.master
@@ -32,6 +32,7 @@ TESTS = test-float.c \
test-forward.c \
test-sou.c \
test-function.c \
+ test-qualifiers.c \
test-merge-static/Makefile.ctftest \
test-merge-static/test-a.c \
test-merge-static/test-b.c \
@@ -73,6 +74,7 @@ CHECKS = check-float-32 \
check-forward-32 \
check-forward-64 \
check-function \
+ check-qualifiers \
check-merge-static \
check-merge-forward-32 \
check-merge-forward-64 \
@@ -96,6 +98,8 @@ ROOTSCRIPTS := FILEMODE = 0555
include $(SRC)/cmd/Makefile.cmd
include $(SRC)/test/Makefile.com
+CSTD = $(CSTD_GNU99)
+
LDLIBS += -lctf
check-merge-static := LDLIBS += -lelf
diff --git a/usr/src/test/util-tests/tests/ctf/check-array.c b/usr/src/test/util-tests/tests/ctf/check-array.c
index c694726a3f..be7a192480 100644
--- a/usr/src/test/util-tests/tests/ctf/check-array.c
+++ b/usr/src/test/util-tests/tests/ctf/check-array.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -105,7 +105,7 @@ main(int argc, char *argv[])
ret = EXIT_FAILURE;
for (d = 0; descents[d].cdt_sym != NULL; d++) {
if (!ctftest_check_descent(descents[d].cdt_sym, fp,
- descents[d].cdt_tests)) {
+ descents[d].cdt_tests, B_FALSE)) {
ret = EXIT_FAILURE;
}
}
diff --git a/usr/src/test/util-tests/tests/ctf/check-common.c b/usr/src/test/util-tests/tests/ctf/check-common.c
index 8aa5449cac..0b29b8be6d 100644
--- a/usr/src/test/util-tests/tests/ctf/check-common.c
+++ b/usr/src/test/util-tests/tests/ctf/check-common.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -248,7 +248,7 @@ ctftest_check_symbols(ctf_file_t *fp, const check_symbol_t *tests)
boolean_t
ctftest_check_descent(const char *symbol, ctf_file_t *fp,
- const check_descent_t *tests)
+ const check_descent_t *tests, boolean_t quiet)
{
ctf_id_t base;
uint_t layer = 0;
@@ -268,65 +268,86 @@ ctftest_check_descent(const char *symbol, ctf_file_t *fp,
ctf_arinfo_t ari;
if (base == CTF_ERR) {
- warnx("encountered non-reference type at layer %u "
- "while still expecting type %s for symbol %s",
- layer, tests->cd_tname, symbol);
+ if (!quiet) {
+ warnx("encountered non-reference type at layer "
+ "%u while still expecting type %s for "
+ "symbol %s", layer,
+ tests->cd_tname, symbol);
+ }
return (B_FALSE);
}
tid = ctftest_lookup_type(fp, tests->cd_tname);
if (tid == CTF_ERR) {
- warnx("failed to lookup type %s", tests->cd_tname);
+ if (!quiet) {
+ warnx("failed to lookup type %s",
+ tests->cd_tname);
+ }
return (B_FALSE);
}
if (tid != base) {
- warnx("type mismatch at layer %u: found id %u, but "
- "expecting type id %u for type %s, symbol %s",
- layer, base, tid, tests->cd_tname, symbol);
+ if (!quiet) {
+ warnx("type mismatch at layer %u: found id %u, "
+ "but expecting type id %u for type %s, "
+ "symbol %s", layer, base, tid,
+ tests->cd_tname, symbol);
+ }
return (B_FALSE);
}
kind = ctf_type_kind(fp, base);
if (kind != tests->cd_kind) {
- warnx("type kind mismatch at layer %u: found kind %u, "
- "but expected kind %u for %s, symbol %s", layer,
- kind, tests->cd_kind, tests->cd_tname, symbol);
+ if (!quiet) {
+ warnx("type kind mismatch at layer %u: found "
+ "kind %u, but expected kind %u for %s, "
+ "symbol %s", layer, kind, tests->cd_kind,
+ tests->cd_tname, symbol);
+ }
return (B_FALSE);
}
switch (kind) {
case CTF_K_ARRAY:
if (ctf_array_info(fp, base, &ari) == CTF_ERR) {
- warnx("failed to lookup array info at layer "
- "%u for type %s, symbol %s: %s", base,
- tests->cd_tname, symbol,
- ctf_errmsg(ctf_errno(fp)));
+ if (!quiet) {
+ warnx("failed to lookup array info at "
+ "layer %u for type %s, symbol "
+ "%s: %s", base, tests->cd_tname,
+ symbol, ctf_errmsg(ctf_errno(fp)));
+ }
return (B_FALSE);
}
if (tests->cd_nents != ari.ctr_nelems) {
- warnx("array element mismatch at layer %u "
- "for type %s, symbol %s: found %u, "
- "expected %u", layer, tests->cd_tname,
- symbol, ari.ctr_nelems, tests->cd_nents);
+ if (!quiet) {
+ warnx("array element mismatch at layer "
+ "%u for type %s, symbol %s: found "
+ "%u, expected %u", layer,
+ tests->cd_tname, symbol,
+ ari.ctr_nelems, tests->cd_nents);
+ }
return (B_FALSE);
}
tid = ctftest_lookup_type(fp, tests->cd_contents);
if (tid == CTF_ERR) {
- warnx("failed to look up type %s",
- tests->cd_contents);
+ if (!quiet) {
+ warnx("failed to look up type %s",
+ tests->cd_contents);
+ }
return (B_FALSE);
}
if (ari.ctr_contents != tid) {
- warnx("array contents mismatch at layer %u "
- "for type %s, symbol %s: found %u, "
- "expected %s/%u", layer, tests->cd_tname,
- symbol, ari.ctr_contents,
- tests->cd_contents, tid);
-
+ if (!quiet) {
+ warnx("array contents mismatch at "
+ "layer %u for type %s, symbol %s: "
+ "found %u, expected %s/%u", layer,
+ tests->cd_tname, symbol,
+ ari.ctr_contents,
+ tests->cd_contents, tid);
+ }
return (B_FALSE);
}
base = ari.ctr_contents;
@@ -341,8 +362,10 @@ ctftest_check_descent(const char *symbol, ctf_file_t *fp,
}
if (base != CTF_ERR) {
- warnx("found additional type %u in chain, but expected no more",
- base);
+ if (!quiet) {
+ warnx("found additional type %u in chain, "
+ "but expected no more", base);
+ }
return (B_FALSE);
}
diff --git a/usr/src/test/util-tests/tests/ctf/check-common.h b/usr/src/test/util-tests/tests/ctf/check-common.h
index f78fb2f00c..20ed6b87af 100644
--- a/usr/src/test/util-tests/tests/ctf/check-common.h
+++ b/usr/src/test/util-tests/tests/ctf/check-common.h
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
#ifndef _CHECK_COMMON_H
@@ -103,7 +103,7 @@ extern boolean_t ctftest_check_symbols(ctf_file_t *, const check_symbol_t *);
* type and checks against it with each subsequent entry.
*/
extern boolean_t ctftest_check_descent(const char *, ctf_file_t *,
- const check_descent_t *);
+ const check_descent_t *, boolean_t);
/*
* Checks that all of the listed members of an enum are present and have the
diff --git a/usr/src/test/util-tests/tests/ctf/check-enum.c b/usr/src/test/util-tests/tests/ctf/check-enum.c
index 79d6f795ed..a5b3091e68 100644
--- a/usr/src/test/util-tests/tests/ctf/check-enum.c
+++ b/usr/src/test/util-tests/tests/ctf/check-enum.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -124,7 +124,7 @@ main(int argc, char *argv[])
ret = EXIT_FAILURE;
for (d = 0; descents[d].cdt_sym != NULL; d++) {
if (!ctftest_check_descent(descents[d].cdt_sym, fp,
- descents[d].cdt_tests)) {
+ descents[d].cdt_tests, B_FALSE)) {
ret = EXIT_FAILURE;
}
}
diff --git a/usr/src/test/util-tests/tests/ctf/check-forward.c b/usr/src/test/util-tests/tests/ctf/check-forward.c
index 2b00209fce..7418b9922e 100644
--- a/usr/src/test/util-tests/tests/ctf/check-forward.c
+++ b/usr/src/test/util-tests/tests/ctf/check-forward.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -109,7 +109,7 @@ main(int argc, char *argv[])
for (j = 0; descents[j].cdt_sym != NULL; j++) {
if (!ctftest_check_descent(descents[j].cdt_sym, fp,
- descents[j].cdt_tests)) {
+ descents[j].cdt_tests, B_FALSE)) {
ret = EXIT_FAILURE;
}
}
diff --git a/usr/src/test/util-tests/tests/ctf/check-qualifiers.c b/usr/src/test/util-tests/tests/ctf/check-qualifiers.c
new file mode 100644
index 0000000000..bd619a94c0
--- /dev/null
+++ b/usr/src/test/util-tests/tests/ctf/check-qualifiers.c
@@ -0,0 +1,318 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019, Joyent, Inc.
+ */
+
+/*
+ * Check qualifier encoding. Note that the needed_qualifier() workaround applies
+ * to most of these.
+ */
+
+#include "check-common.h"
+
+static check_descent_t check_descent_const_union_array_gcc4[] = {
+ { "const union const_union [5]", CTF_K_CONST },
+ { "union const_union [5]", CTF_K_ARRAY, "union const_union", 5 },
+ { "union const_union", CTF_K_UNION },
+ { NULL }
+};
+
+static check_descent_t check_descent_const_union_array_gcc7[] = {
+ { "const union const_union [5]", CTF_K_ARRAY,
+ "const union const_union", 5 },
+ { "const union const_union", CTF_K_CONST },
+ { "union const_union", CTF_K_UNION },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_const_union_array[] = {
+ { "const_union_array", check_descent_const_union_array_gcc4 },
+ { "const_union_array", check_descent_const_union_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_const_struct_array_gcc4[] = {
+ { "const struct const_struct [7]", CTF_K_CONST },
+ { "struct const_struct [7]", CTF_K_ARRAY, "struct const_struct", 7 },
+ { "struct const_struct", CTF_K_STRUCT },
+ { NULL }
+};
+
+static check_descent_t check_descent_const_struct_array_gcc7[] = {
+ { "const struct const_struct [7]", CTF_K_ARRAY,
+ "const struct const_struct", 7 },
+ { "const struct const_struct", CTF_K_CONST },
+ { "struct const_struct", CTF_K_STRUCT },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_const_struct_array[] = {
+ { "const_struct_array", check_descent_const_struct_array_gcc4 },
+ { "const_struct_array", check_descent_const_struct_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_volatile_struct_array_gcc4[] = {
+ { "volatile struct volatile_struct [9]", CTF_K_VOLATILE },
+ { "struct volatile_struct [9]", CTF_K_ARRAY,
+ "struct volatile_struct", 9 },
+ { "struct volatile_struct", CTF_K_STRUCT },
+ { NULL }
+};
+
+static check_descent_t check_descent_volatile_struct_array_gcc7[] = {
+ { "volatile struct volatile_struct [9]", CTF_K_ARRAY,
+ "volatile struct volatile_struct", 9 },
+ { "volatile struct volatile_struct", CTF_K_VOLATILE },
+ { "struct volatile_struct", CTF_K_STRUCT },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_volatile_struct_array[] = {
+ { "volatile_struct_array", check_descent_volatile_struct_array_gcc4 },
+ { "volatile_struct_array", check_descent_volatile_struct_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_c_int_array_gcc4[] = {
+ { "const int [11]", CTF_K_CONST },
+ { "int [11]", CTF_K_ARRAY, "int", 11 },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_t check_descent_c_int_array_gcc7[] = {
+ { "const int [11]", CTF_K_ARRAY, "const int", 11 },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_c_int_array[] = {
+ { "c_int_array", check_descent_c_int_array_gcc4 },
+ { "c_int_array", check_descent_c_int_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_cv_int_array_gcc4[] = {
+ { "const volatile int [13]", CTF_K_CONST },
+ { "volatile int [13]", CTF_K_VOLATILE },
+ { "int [13]", CTF_K_ARRAY, "int", 13 },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_t check_descent_cv_int_array_gcc7[] = {
+ { "volatile const int [13]", CTF_K_ARRAY, "volatile const int", 13 },
+ { "volatile const int", CTF_K_VOLATILE },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_cv_int_array[] = {
+ { "cv_int_array", check_descent_cv_int_array_gcc4 },
+ { "cv_int_array", check_descent_cv_int_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_vc_int_array_gcc4[] = {
+ { "const volatile int [15]", CTF_K_CONST },
+ { "volatile int [15]", CTF_K_VOLATILE },
+ { "int [15]", CTF_K_ARRAY, "int", 15 },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_t check_descent_vc_int_array_gcc7[] = {
+ { "volatile const int [15]", CTF_K_ARRAY, "volatile const int", 15 },
+ { "volatile const int", CTF_K_VOLATILE },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_vc_int_array[] = {
+ { "vc_int_array", check_descent_vc_int_array_gcc4 },
+ { "vc_int_array", check_descent_vc_int_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_vc_int_array2_gcc4[] = {
+ { "const volatile int [17]", CTF_K_CONST },
+ { "volatile int [17]", CTF_K_VOLATILE },
+ { "int [17]", CTF_K_ARRAY, "int", 17 },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_t check_descent_vc_int_array2_gcc7[] = {
+ { "volatile const int [17]", CTF_K_ARRAY, "volatile const int", 17 },
+ { "volatile const int", CTF_K_VOLATILE },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_vc_int_array2[] = {
+ { "vc_int_array2", check_descent_vc_int_array2_gcc4 },
+ { "vc_int_array2", check_descent_vc_int_array2_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_c_2d_array_gcc4[] = {
+ { "const int [4][2]", CTF_K_CONST },
+ { "int [4][2]", CTF_K_ARRAY, "int [2]", 4 },
+ { "int [2]", CTF_K_ARRAY, "int", 2 },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_t check_descent_c_2d_array_gcc7[] = {
+ { "const int [4][2]", CTF_K_ARRAY, "const int [2]", 4 },
+ { "const int [2]", CTF_K_ARRAY, "const int", 2 },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_c_2d_array[] = {
+ { "c_2d_array", check_descent_c_2d_array_gcc4 },
+ { "c_2d_array", check_descent_c_2d_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_cv_3d_array_gcc4[] = {
+ { "const volatile int [3][2][1]", CTF_K_CONST },
+ { "volatile int [3][2][1]", CTF_K_VOLATILE },
+ { "int [3][2][1]", CTF_K_ARRAY, "int [2][1]", 3 },
+ { "int [2][1]", CTF_K_ARRAY, "int [1]", 2 },
+ { "int [1]", CTF_K_ARRAY, "int", 1 },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_t check_descent_cv_3d_array_gcc7[] = {
+ { "volatile const int [3][2][1]", CTF_K_ARRAY,
+ "volatile const int [2][1]", 3 },
+ { "volatile const int [2][1]", CTF_K_ARRAY,
+ "volatile const int [1]", 2 },
+ { "volatile const int [1]", CTF_K_ARRAY, "volatile const int", 1 },
+ { "volatile const int", CTF_K_VOLATILE },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_cv_3d_array[] = {
+ { "cv_3d_array", check_descent_cv_3d_array_gcc4 },
+ { "cv_3d_array", check_descent_cv_3d_array_gcc7 },
+ { NULL }
+};
+
+static check_descent_t check_descent_ptr_to_const_int[] = {
+ { "const int *", CTF_K_POINTER },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_ptr_to_const_int[] = {
+ { "ptr_to_const_int", check_descent_ptr_to_const_int },
+ { NULL }
+};
+
+static check_descent_t check_descent_const_ptr_to_int[] = {
+ { "int *const", CTF_K_CONST },
+ { "int *", CTF_K_POINTER },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_const_ptr_to_int[] = {
+ { "const_ptr_to_int", check_descent_const_ptr_to_int },
+ { NULL }
+};
+
+static check_descent_t check_descent_const_ptr_to_const_int[] = {
+ { "const int *const", CTF_K_CONST },
+ { "const int *", CTF_K_POINTER },
+ { "const int", CTF_K_CONST },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_test_t alt_descents_const_ptr_to_const_int[] = {
+ { "const_ptr_to_const_int", check_descent_const_ptr_to_const_int },
+ { NULL }
+};
+
+static check_descent_test_t *alt_descents[] = {
+ alt_descents_const_union_array,
+ alt_descents_const_struct_array,
+ alt_descents_volatile_struct_array,
+ alt_descents_c_int_array,
+ alt_descents_cv_int_array,
+ alt_descents_vc_int_array,
+ alt_descents_vc_int_array2,
+ alt_descents_c_2d_array,
+ alt_descents_cv_3d_array,
+ alt_descents_ptr_to_const_int,
+ alt_descents_const_ptr_to_int,
+ alt_descents_const_ptr_to_const_int,
+ NULL
+};
+
+int
+main(int argc, char *argv[])
+{
+ int i, ret = 0;
+
+ if (argc < 2) {
+ errx(EXIT_FAILURE, "missing test files");
+ }
+
+ for (i = 1; i < argc; i++) {
+ ctf_file_t *fp;
+
+ if ((fp = ctf_open(argv[i], &ret)) == NULL) {
+ warnx("failed to open %s: %s", argv[i],
+ ctf_errmsg(ret));
+ ret = EXIT_FAILURE;
+ continue;
+ }
+
+ for (uint_t j = 0; alt_descents[j] != NULL; j++) {
+ check_descent_test_t *descents = alt_descents[j];
+ int alt_ok = 0;
+
+ for (uint_t k = 0; descents[k].cdt_sym != NULL; k++) {
+ if (ctftest_check_descent(descents[k].cdt_sym,
+ fp, descents[k].cdt_tests, B_TRUE)) {
+ alt_ok = 1;
+ break;
+ }
+ }
+
+ if (!alt_ok) {
+ warnx("all descents failed for %s",
+ descents[0].cdt_sym);
+ ret = EXIT_FAILURE;
+ }
+ }
+
+ ctf_close(fp);
+ }
+
+ return (ret);
+}
diff --git a/usr/src/test/util-tests/tests/ctf/check-reference.c b/usr/src/test/util-tests/tests/ctf/check-reference.c
index 05c0469c15..a513838092 100644
--- a/usr/src/test/util-tests/tests/ctf/check-reference.c
+++ b/usr/src/test/util-tests/tests/ctf/check-reference.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -131,18 +131,6 @@ static check_descent_t check_descent_g[] = {
{ NULL }
};
-static check_descent_t check_descent_cvh[] = {
- { "const volatile foo_t *", CTF_K_POINTER },
- { "const volatile foo_t", CTF_K_CONST },
- { "volatile foo_t", CTF_K_VOLATILE },
- { "foo_t", CTF_K_TYPEDEF },
- { "int *const *", CTF_K_POINTER },
- { "int *const", CTF_K_CONST },
- { "int *", CTF_K_POINTER },
- { "int", CTF_K_INTEGER },
- { NULL }
-};
-
static check_descent_test_t descents[] = {
{ "aa", check_descent_aa },
{ "b", check_descent_b },
@@ -156,10 +144,43 @@ static check_descent_test_t descents[] = {
{ "cve", check_descent_cve },
{ "f", check_descent_f },
{ "g", check_descent_g },
- { "cvh", check_descent_cvh },
{ NULL }
};
+static check_descent_t check_descent_cvh_gcc4[] = {
+ { "const volatile foo_t *", CTF_K_POINTER },
+ { "const volatile foo_t", CTF_K_CONST },
+ { "volatile foo_t", CTF_K_VOLATILE },
+ { "foo_t", CTF_K_TYPEDEF },
+ { "int *const *", CTF_K_POINTER },
+ { "int *const", CTF_K_CONST },
+ { "int *", CTF_K_POINTER },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+static check_descent_t check_descent_cvh_gcc7[] = {
+ { "volatile const foo_t *", CTF_K_POINTER },
+ { "volatile const foo_t", CTF_K_VOLATILE },
+ { "const foo_t", CTF_K_CONST },
+ { "foo_t", CTF_K_TYPEDEF },
+ { "int *const *", CTF_K_POINTER },
+ { "int *const", CTF_K_CONST },
+ { "int *", CTF_K_POINTER },
+ { "int", CTF_K_INTEGER },
+ { NULL }
+};
+
+/*
+ * GCC versions differ in how they order qualifiers, which is a shame for
+ * round-tripping; but as they're clearly both valid, we should cope. We'll
+ * just insist that at least one of these checks passes.
+ */
+static check_descent_test_t alt_descents[] = {
+ { "cvh", check_descent_cvh_gcc4 },
+ { "cvh", check_descent_cvh_gcc7 },
+};
+
int
main(int argc, char *argv[])
{
@@ -171,6 +192,7 @@ main(int argc, char *argv[])
for (i = 1; i < argc; i++) {
ctf_file_t *fp;
+ int alt_ok = 0;
uint_t d;
if ((fp = ctf_open(argv[i], &ret)) == NULL) {
@@ -186,10 +208,25 @@ main(int argc, char *argv[])
ret = EXIT_FAILURE;
for (d = 0; descents[d].cdt_sym != NULL; d++) {
if (!ctftest_check_descent(descents[d].cdt_sym, fp,
- descents[d].cdt_tests)) {
+ descents[d].cdt_tests, B_FALSE)) {
ret = EXIT_FAILURE;
}
}
+
+ for (d = 0; alt_descents[d].cdt_sym != NULL; d++) {
+ if (ctftest_check_descent(alt_descents[d].cdt_sym, fp,
+ alt_descents[d].cdt_tests, B_TRUE)) {
+ alt_ok = 1;
+ break;
+ }
+ }
+
+ if (!alt_ok) {
+ warnx("all descents failed for %s",
+ alt_descents[0].cdt_sym);
+ ret = EXIT_FAILURE;
+ }
+
ctf_close(fp);
}
diff --git a/usr/src/test/util-tests/tests/ctf/check-sou.c b/usr/src/test/util-tests/tests/ctf/check-sou.c
index 32bcc20b6d..e991452ce2 100644
--- a/usr/src/test/util-tests/tests/ctf/check-sou.c
+++ b/usr/src/test/util-tests/tests/ctf/check-sou.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
/*
@@ -345,17 +345,33 @@ static check_descent_t check_descent_forward[] = {
{ NULL }
};
-static check_descent_t check_descent_regress[] = {
+static check_descent_test_t descents[] = {
+ { "head", check_descent_head },
+ { "forward", check_descent_forward },
+ { NULL }
+};
+
+static check_descent_t check_descent_regress_gcc4[] = {
{ "const union regress [9]", CTF_K_CONST },
{ "union regress [9]", CTF_K_ARRAY, "union regress", 9 },
{ "union regress", CTF_K_UNION },
{ NULL }
};
-static check_descent_test_t descents[] = {
- { "head", check_descent_head },
- { "forward", check_descent_forward },
- { "regress", check_descent_regress },
+static check_descent_t check_descent_regress_gcc7[] = {
+ { "const union regress [9]", CTF_K_ARRAY, "const union regress", 9 },
+ { "const union regress", CTF_K_CONST },
+ { "union regress", CTF_K_UNION },
+ { NULL }
+};
+
+/*
+ * See needed_array_qualifier(): applying this fix means the qualifier order is
+ * different between GCC versions. Accept either form.
+ */
+static check_descent_test_t alt_descents[] = {
+ { "regress", check_descent_regress_gcc4 },
+ { "regress", check_descent_regress_gcc7 },
{ NULL }
};
@@ -370,6 +386,7 @@ main(int argc, char *argv[])
for (i = 1; i < argc; i++) {
ctf_file_t *fp;
+ int alt_ok = 0;
uint_t j;
if ((fp = ctf_open(argv[i], &ret)) == NULL) {
@@ -385,11 +402,25 @@ main(int argc, char *argv[])
ret = EXIT_FAILURE;
for (j = 0; descents[j].cdt_sym != NULL; j++) {
if (!ctftest_check_descent(descents[j].cdt_sym, fp,
- descents[j].cdt_tests)) {
+ descents[j].cdt_tests, B_FALSE)) {
ret = EXIT_FAILURE;
}
}
+ for (j = 0; alt_descents[j].cdt_sym != NULL; j++) {
+ if (ctftest_check_descent(alt_descents[j].cdt_sym, fp,
+ alt_descents[j].cdt_tests, B_TRUE)) {
+ alt_ok = 1;
+ break;
+ }
+ }
+
+ if (!alt_ok) {
+ warnx("all descents failed for %s",
+ alt_descents[0].cdt_sym);
+ ret = EXIT_FAILURE;
+ }
+
for (j = 0; members[j].cmt_type != NULL; j++) {
if (!ctftest_check_members(members[j].cmt_type, fp,
members[j].cmt_kind, members[j].cmt_size,
diff --git a/usr/src/test/util-tests/tests/ctf/test-merge-weak/test-merge-weak.c b/usr/src/test/util-tests/tests/ctf/test-merge-weak/test-merge-weak.c
index 7d47c02fea..7321581287 100644
--- a/usr/src/test/util-tests/tests/ctf/test-merge-weak/test-merge-weak.c
+++ b/usr/src/test/util-tests/tests/ctf/test-merge-weak/test-merge-weak.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (c) 2019, Joyent, Inc.
+ * Copyright 2019, Joyent, Inc.
*/
#include <stdlib.h>
@@ -26,6 +26,8 @@ _mumble(void)
return ((int)arc4random());
}
+extern int mumble(void);
+
int
main(void)
{
diff --git a/usr/src/test/util-tests/tests/ctf/test-qualifiers.c b/usr/src/test/util-tests/tests/ctf/test-qualifiers.c
new file mode 100755
index 0000000000..b26a6c555b
--- /dev/null
+++ b/usr/src/test/util-tests/tests/ctf/test-qualifiers.c
@@ -0,0 +1,42 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019, Joyent, Inc.
+ */
+
+/*
+ * Make sure that we're encoding qualifiers correctly.
+ */
+
+const union const_union {
+ int i;
+} const_union_array[5];
+
+const struct const_struct {
+ int i;
+} const_struct_array[7];
+
+volatile struct volatile_struct {
+ int i;
+} volatile_struct_array[9];
+
+const int c_int_array[11];
+const volatile int cv_int_array[13];
+volatile const int vc_int_array[15];
+volatile int const vc_int_array2[17];
+
+const int c_2d_array[4][2];
+const volatile int cv_3d_array[3][2][1];
+
+const int *ptr_to_const_int;
+int * const const_ptr_to_int;
+const int * const const_ptr_to_const_int;