diff options
author | John Levon <john.levon@joyent.com> | 2019-04-11 14:03:27 +0000 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2019-05-03 02:15:58 -0700 |
commit | 6ef284f1d464c08bc420048a0b211080cb9fe009 (patch) | |
tree | 899285312544e2f8939f8e248283cbd4ae45e6d2 | |
parent | 59d77acb140ef81a3e7784b472f41ff409b72114 (diff) | |
download | illumos-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.c | 84 | ||||
-rw-r--r-- | usr/src/common/ctf/ctf_impl.h | 5 | ||||
-rw-r--r-- | usr/src/common/ctf/ctf_lookup.c | 51 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/ctf_dwarf.c | 109 | ||||
-rw-r--r-- | usr/src/pkg/manifests/system-test-utiltest.mf | 70 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/Makefile | 6 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-array.c | 4 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-common.c | 83 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-common.h | 4 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-enum.c | 4 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-forward.c | 4 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-qualifiers.c | 318 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-reference.c | 67 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-sou.c | 45 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/test-merge-weak/test-merge-weak.c | 4 | ||||
-rwxr-xr-x | usr/src/test/util-tests/tests/ctf/test-qualifiers.c | 42 |
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; |