diff options
author | John Levon <john.levon@joyent.com> | 2020-01-29 07:27:16 -0800 |
---|---|---|
committer | John Levon <john.levon@joyent.com> | 2020-02-12 03:18:36 -0800 |
commit | fe2dc8bddec347e173d402f53feeb492640a9f98 (patch) | |
tree | dc27791c1d158d314fb5239a0b15a208bf695955 /usr/src | |
parent | d5d2dbe51affdd94ab32688a7e92dd23ef5b3ba9 (diff) | |
download | illumos-joyent-fe2dc8bddec347e173d402f53feeb492640a9f98.tar.gz |
12259 CTF shouldn't assume enum size
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/ctfdump/ctfdump.c | 22 | ||||
-rw-r--r-- | usr/src/common/ctf/ctf_create.c | 55 | ||||
-rw-r--r-- | usr/src/common/ctf/ctf_impl.h | 4 | ||||
-rw-r--r-- | usr/src/common/ctf/ctf_types.c | 18 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/ctf_dwarf.c | 45 | ||||
-rw-r--r-- | usr/src/lib/libctf/common/ctf_merge.c | 9 | ||||
-rw-r--r-- | usr/src/lib/libdtrace/common/dt_decl.c | 4 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-common.c | 21 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-common.h | 12 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/check-enum.c | 18 | ||||
-rw-r--r-- | usr/src/test/util-tests/tests/ctf/test-enum.c | 32 | ||||
-rw-r--r-- | usr/src/uts/common/sys/ctf_api.h | 4 |
12 files changed, 194 insertions, 50 deletions
diff --git a/usr/src/cmd/ctfdump/ctfdump.c b/usr/src/cmd/ctfdump/ctfdump.c index b77ef56a24..a2e668d266 100644 --- a/usr/src/cmd/ctfdump/ctfdump.c +++ b/usr/src/cmd/ctfdump/ctfdump.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* @@ -613,7 +613,16 @@ ctfdump_types_cb(ctf_id_t id, boolean_t root, void *arg) } break; case CTF_K_ENUM: - ctfdump_printf(CTFDUMP_TYPES, "%s\n", name); + size = ctf_type_size(g_fp, id); + + /* Only the oddest enums are worth reporting on size. */ + if (size != CTF_ERR && size != sizeof (int)) { + ctfdump_printf(CTFDUMP_TYPES, "%s (%zd bytes)\n", + name, size); + } else { + ctfdump_printf(CTFDUMP_TYPES, "%s\n", name); + } + count = 0; if (ctf_enum_iter(g_fp, id, ctfdump_enum_cb, &count) != 0) ctfdump_fatal("failed to iterate enumerators of %s: " @@ -805,7 +814,14 @@ ctfsrc_type(ctf_id_t id, const char *name) "%s\n", name, ctf_errmsg(ctf_errno(g_fp))); } - printf("};\n\n"); + size = ctf_type_size(g_fp, id); + + /* Only the oddest enums are worth reporting on size. */ + if (size != CTF_ERR && size != sizeof (int)) { + printf("} /* 0x%x bytes */;\n\n", size); + } else { + printf("};\n\n"); + } break; case CTF_K_TYPEDEF: /* diff --git a/usr/src/common/ctf/ctf_create.c b/usr/src/common/ctf/ctf_create.c index d88283e8f5..c1027aa60e 100644 --- a/usr/src/common/ctf/ctf_create.c +++ b/usr/src/common/ctf/ctf_create.c @@ -25,7 +25,7 @@ * Use is subject to license terms. */ /* - * Copyright (c) 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ #include <sys/sysmacros.h> @@ -35,6 +35,14 @@ #include <sys/debug.h> /* + * SSIZE_MAX is not available in the kernel, so we define it here rather than + * accidentally inject into headers where it's not wanted. + */ +#ifndef SSIZE_MAX +#define SSIZE_MAX (LONG_MAX) +#endif + +/* * This static string is used as the template for initially populating a * dynamic container's string table. We always store \0 in the first byte, * and we use the generic string "PARENT" to mark this container's parent @@ -1246,14 +1254,22 @@ ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name) return (type); } +/* + * If size is 0, we use the standard integer size. This is almost always the + * case, except for packed enums. + */ ctf_id_t -ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name) +ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name, size_t size) { ctf_hash_t *hp = &fp->ctf_enums; ctf_helem_t *hep = NULL; ctf_dtdef_t *dtd = NULL; ctf_id_t type = CTF_ERR; + /* Check we could return something valid in ctf_type_size. */ + if (size > SSIZE_MAX) + return (ctf_set_errno(fp, EINVAL)); + if (name != NULL) hep = ctf_hash_lookup(hp, fp, name, strlen(name)); @@ -1272,7 +1288,9 @@ ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name) VERIFY(type != CTF_ERR); dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0); - dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int; + + ctf_set_ctt_size(&dtd->dtd_data, size == 0 ? + fp->ctf_dmodel->ctd_int : size); /* * Always dirty in case we modified a forward. @@ -1551,12 +1569,7 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type, ssize = MAX(ssize, msize); } - if (ssize > CTF_MAX_SIZE) { - dtd->dtd_data.ctt_size = CTF_LSIZE_SENT; - dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize); - dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize); - } else - dtd->dtd_data.ctt_size = (ushort_t)ssize; + ctf_set_ctt_size(&dtd->dtd_data, ssize); dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1); ctf_list_append(&dtd->dtd_u.dtu_members, dmd); @@ -1693,7 +1706,6 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) ctf_dtdef_t *dtd; ctf_funcinfo_t ctc; - ssize_t size; ctf_hash_t *hp; ctf_helem_t *hep; @@ -1888,12 +1900,8 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0) errs++; /* increment errs and fail at bottom of case */ - if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) { - dtd->dtd_data.ctt_size = CTF_LSIZE_SENT; - dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); - dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); - } else - dtd->dtd_data.ctt_size = (ushort_t)size; + ctf_set_ctt_size(&dtd->dtd_data, + ctf_type_size(src_fp, src_type)); dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen); @@ -1928,7 +1936,12 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) ctf_enum_iter(dst_fp, dst_type, enumcmp, &src)) return (ctf_set_errno(dst_fp, ECTF_CONFLICT)); } else { - dst_type = ctf_add_enum(dst_fp, flag, name); + ssize_t size = ctf_type_size(src_fp, src_type); + + if (size == CTF_ERR) + return (CTF_ERR); /* errno is set for us */ + + dst_type = ctf_add_enum(dst_fp, flag, name, size); if ((dst.ctb_type = dst_type) == CTF_ERR || ctf_enum_iter(src_fp, src_type, enumadd, &dst)) return (CTF_ERR); /* errno is set for us */ @@ -2165,13 +2178,7 @@ ctf_set_size(ctf_file_t *fp, ctf_id_t id, const ulong_t newsz) if (newsz < oldsz) return (ctf_set_errno(fp, EINVAL)); - if (newsz > CTF_MAX_SIZE) { - dtd->dtd_data.ctt_size = CTF_LSIZE_SENT; - dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(newsz); - dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(newsz); - } else { - dtd->dtd_data.ctt_size = (ushort_t)newsz; - } + ctf_set_ctt_size(&dtd->dtd_data, newsz); fp->ctf_flags |= LCTF_DIRTY; return (0); diff --git a/usr/src/common/ctf/ctf_impl.h b/usr/src/common/ctf/ctf_impl.h index b82fb7e36e..7064abad15 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 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ #ifndef _CTF_IMPL_H @@ -254,6 +254,8 @@ struct ctf_file { extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *, ssize_t *, ssize_t *); +extern void ctf_set_ctt_size(ctf_type_t *, ssize_t); + extern const ctf_type_t *ctf_lookup_by_id(ctf_file_t **, ctf_id_t); extern ctf_file_t *ctf_fdcreate_int(int, int *, ctf_sect_t *); diff --git a/usr/src/common/ctf/ctf_types.c b/usr/src/common/ctf/ctf_types.c index 18d2d3d88a..6456f8a042 100644 --- a/usr/src/common/ctf/ctf_types.c +++ b/usr/src/common/ctf/ctf_types.c @@ -25,7 +25,7 @@ * Use is subject to license terms. */ /* - * Copyright 2018 Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ #include <ctf_impl.h> @@ -54,6 +54,18 @@ ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep, return (size); } +void +ctf_set_ctt_size(ctf_type_t *tp, ssize_t size) +{ + if (size > CTF_MAX_SIZE) { + tp->ctt_size = CTF_LSIZE_SENT; + tp->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size); + tp->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size); + } else { + tp->ctt_size = (ushort_t)size; + } +} + /* * Iterate over the members of a STRUCT or UNION. We pass the name, member * type, and offset of each member to the specified callback function. @@ -481,7 +493,7 @@ ctf_type_size(ctf_file_t *fp, ctf_id_t type) return (0); case CTF_K_ENUM: - return (fp->ctf_dmodel->ctd_int); + return (ctf_get_ctt_size(fp, tp, NULL, NULL)); case CTF_K_ARRAY: /* @@ -578,8 +590,6 @@ ctf_type_align(ctf_file_t *fp, ctf_id_t type) } case CTF_K_ENUM: - return (fp->ctf_dmodel->ctd_int); - default: return (ctf_get_ctt_size(fp, tp, NULL, NULL)); } diff --git a/usr/src/lib/libctf/common/ctf_dwarf.c b/usr/src/lib/libctf/common/ctf_dwarf.c index 3f57ef6704..1aa0f2e5e1 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 2020 Joyent, Inc. */ /* @@ -1213,7 +1213,6 @@ ctf_dwarf_fixup_sou(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t base, boolean_t add) int ret, kind; Dwarf_Die child, memb; Dwarf_Unsigned size; - ulong_t nsz; kind = ctf_type_kind(cup->cu_ctfp, base); VERIFY(kind != CTF_ERR); @@ -1306,8 +1305,7 @@ next: /* Finally set the size of the structure to the actual byte size */ if ((ret = ctf_dwarf_unsigned(cup, die, DW_AT_byte_size, &size)) != 0) return (ret); - nsz = size; - if ((ctf_set_size(cup->cu_ctfp, base, nsz)) == CTF_ERR) { + if ((ctf_set_size(cup->cu_ctfp, base, size)) == CTF_ERR) { int e = ctf_errno(cup->cu_ctfp); (void) snprintf(cup->cu_errbuf, cup->cu_errlen, "failed to set type size for %d to 0x%x: %s", base, @@ -1614,20 +1612,53 @@ ctf_dwarf_create_reference(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, return (ctf_dwmap_add(cup, *idp, die, B_FALSE)); } +/* + * Get the size of the type of a particular die. Note that this is a simple + * version that doesn't attempt to traverse further than expecting a single + * sized type reference (so no qualifiers etc.). Nor does it attempt to do as + * much as ctf_type_size() - which we cannot use here as that doesn't look up + * dynamic types, and we don't yet want to do a ctf_update(). + */ static int -ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) +ctf_dwarf_get_type_size(ctf_cu_t *cup, Dwarf_Die die, size_t *sizep) { + const ctf_type_t *t; + Dwarf_Die tdie; + ctf_id_t tid; int ret; - ctf_id_t id; + + if ((ret = ctf_dwarf_refdie(cup, die, DW_AT_type, &tdie)) != 0) + return (ret); + + if ((ret = ctf_dwarf_convert_type(cup, tdie, &tid, + CTF_ADD_NONROOT)) != 0) + return (ret); + + if ((t = ctf_dyn_lookup_by_id(cup->cu_ctfp, tid)) == NULL) + return (ENOENT); + + *sizep = ctf_get_ctt_size(cup->cu_ctfp, t, NULL, NULL); + return (0); +} + +static int +ctf_dwarf_create_enum(ctf_cu_t *cup, Dwarf_Die die, ctf_id_t *idp, int isroot) +{ + size_t size = 0; Dwarf_Die child; + ctf_id_t id; char *name; + int ret; if ((ret = ctf_dwarf_string(cup, die, DW_AT_name, &name)) != 0 && ret != ENOENT) return (ret); if (ret == ENOENT) name = NULL; - id = ctf_add_enum(cup->cu_ctfp, isroot, name); + + (void) ctf_dwarf_get_type_size(cup, die, &size); + + id = ctf_add_enum(cup->cu_ctfp, isroot, name, size); ctf_dprintf("added enum %s (%d)\n", name, id); if (name != NULL) ctf_free(name, strlen(name) + 1); diff --git a/usr/src/lib/libctf/common/ctf_merge.c b/usr/src/lib/libctf/common/ctf_merge.c index 578e667079..a18a2f46ef 100644 --- a/usr/src/lib/libctf/common/ctf_merge.c +++ b/usr/src/lib/libctf/common/ctf_merge.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* @@ -340,15 +340,18 @@ ctf_merge_add_enum(ctf_merge_types_t *cmp, ctf_id_t id) const char *name; ctf_id_t enumid; ctf_merge_enum_t cme; + size_t size; tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id); - name = ctf_strraw(cmp->cm_src, tp->ctt_name); if (CTF_INFO_ISROOT(tp->ctt_info) != 0) flags = CTF_ADD_ROOT; else flags = CTF_ADD_NONROOT; - enumid = ctf_add_enum(cmp->cm_out, flags, name); + name = ctf_strraw(cmp->cm_src, tp->ctt_name); + size = ctf_get_ctt_size(cmp->cm_src, tp, NULL, NULL); + + enumid = ctf_add_enum(cmp->cm_out, flags, name, size); if (enumid == CTF_ERR) return (enumid); diff --git a/usr/src/lib/libdtrace/common/dt_decl.c b/usr/src/lib/libdtrace/common/dt_decl.c index c9bd469ddb..00abd31af3 100644 --- a/usr/src/lib/libdtrace/common/dt_decl.c +++ b/usr/src/lib/libdtrace/common/dt_decl.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 by Delphix. All rights reserved. - * Copyright (c) 2015 Joyent, Inc. All rights reserved. + * Copyright 2020 Joyent, Inc. */ #include <strings.h> @@ -694,7 +694,7 @@ dt_decl_enum(char *name) if (name != NULL && (type = ctf_lookup_by_name(ctfp, n)) != CTF_ERR) { if (ctf_enum_iter(ctfp, type, dt_decl_hasmembers, NULL)) xyerror(D_DECL_TYPERED, "type redeclared: %s\n", n); - } else if ((type = ctf_add_enum(ctfp, flag, name)) == CTF_ERR) { + } else if ((type = ctf_add_enum(ctfp, flag, name, 0)) == CTF_ERR) { xyerror(D_UNKNOWN, "failed to define %s: %s\n", n, ctf_errmsg(ctf_errno(ctfp))); } 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 0b29b8be6d..9b83f70ebd 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 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* @@ -738,6 +738,25 @@ ctftest_check_fptr(const char *type, ctf_file_t *fp, const char *rtype, return (ret); } +boolean_t +ctftest_check_size(const char *type, ctf_file_t *fp, size_t size) +{ + ctf_id_t base; + + if ((base = ctftest_lookup_type(fp, type)) == CTF_ERR) { + warnx("Failed to look up type %s", type); + return (B_FALSE); + } + + if (size != ctf_type_size(fp, base)) { + warnx("%s has bad size, expected %lu, found %lu", + type, size, ctf_type_size(fp, base)); + return (B_FALSE); + } + + return (B_TRUE); +} + typedef struct ctftest_duplicates { ctf_file_t *ctd_fp; char **ctd_names; 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 20ed6b87af..efb848d25b 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 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ #ifndef _CHECK_COMMON_H @@ -87,6 +87,11 @@ typedef struct check_function_test { const char **cft_args; } check_function_test_t; +typedef struct check_size_test { + const char *cst_name; + size_t cst_size; +} check_size_test_t; + /* * Looks up each type and verifies that it matches the expected type. */ @@ -130,6 +135,11 @@ extern boolean_t ctftest_check_fptr(const char *, ctf_file_t *, const char *, uint_t, uint_t, const char **); /* + * Check size of types. + */ +extern boolean_t ctftest_check_size(const char *, ctf_file_t *, size_t); + +/* * Determine whether or not we have a duplicate type or not based on its name. */ extern boolean_t ctftest_duplicates(ctf_file_t *); 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 a5b3091e68..e324619beb 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 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* @@ -101,6 +101,14 @@ static check_enum_test_t enums[] = { { NULL } }; +static check_size_test_t size_enums[] = { + { "enum char_enum", 1 }, + { "enum short_enum", 2 }, + { "enum int_enum", 4 }, + { "enum ll_enum", 8 }, + { NULL } +}; + int main(int argc, char *argv[]) { @@ -135,6 +143,14 @@ main(int argc, char *argv[]) ret = EXIT_FAILURE; } } + + for (d = 0; size_enums[d].cst_name != NULL; d++) { + if (!ctftest_check_size(size_enums[d].cst_name, + fp, size_enums[d].cst_size)) { + ret = EXIT_FAILURE; + } + } + ctf_close(fp); } diff --git a/usr/src/test/util-tests/tests/ctf/test-enum.c b/usr/src/test/util-tests/tests/ctf/test-enum.c index f6bfbfccb0..95174e25f2 100644 --- a/usr/src/test/util-tests/tests/ctf/test-enum.c +++ b/usr/src/test/util-tests/tests/ctf/test-enum.c @@ -10,7 +10,7 @@ */ /* - * Copyright (c) 2019, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ #include <stdint.h> @@ -72,3 +72,33 @@ typedef enum chrono { enum ff6 ff6; ff10_t ff10; chrono_t trigger; + +/* + * Normally enums are integer-sized, but a packed enum is a counter-example, as + * is something like trace_alloc_type_t which can't fit in an int. + */ + +enum char_enum { + CE1, + CE2 +} __attribute__((packed)) ce; + +enum short_enum { + SE1, + SE2, + SE3 = 255, + SE4 = 256, + SE5 = 257 +} __attribute__((packed)) se; + +enum int_enum { + IE1, + IE2, + IE3 = 256, + IE4 = 257 +} ie; + +enum ll_enum { + LLE1 = -1ULL, + LLE2 = -2ULL, +} lle; diff --git a/usr/src/uts/common/sys/ctf_api.h b/usr/src/uts/common/sys/ctf_api.h index 39a2e22179..a04b4032b5 100644 --- a/usr/src/uts/common/sys/ctf_api.h +++ b/usr/src/uts/common/sys/ctf_api.h @@ -24,7 +24,7 @@ * Use is subject to license terms. */ /* - * Copyright 2019 Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ /* @@ -284,7 +284,7 @@ extern int ctf_string_iter(ctf_file_t *, ctf_string_f *, void *); extern ctf_id_t ctf_add_array(ctf_file_t *, uint_t, const ctf_arinfo_t *); extern ctf_id_t ctf_add_const(ctf_file_t *, uint_t, const char *, ctf_id_t); -extern ctf_id_t ctf_add_enum(ctf_file_t *, uint_t, const char *); +extern ctf_id_t ctf_add_enum(ctf_file_t *, uint_t, const char *, size_t); extern ctf_id_t ctf_add_float(ctf_file_t *, uint_t, const char *, const ctf_encoding_t *); extern ctf_id_t ctf_add_forward(ctf_file_t *, uint_t, const char *, uint_t); |