diff options
| author | mws <none@none> | 2006-01-08 14:39:10 -0800 |
|---|---|---|
| committer | mws <none@none> | 2006-01-08 14:39:10 -0800 |
| commit | e4586ebf2f01666696316c178da243993b1a0c04 (patch) | |
| tree | 8b48d38ef0f5c3449bce818de6bc85cbc54e7771 /usr/src/common/ctf | |
| parent | 0578ac30778226273ab5a411148294e23d339851 (diff) | |
| download | illumos-joyent-e4586ebf2f01666696316c178da243993b1a0c04.tar.gz | |
6198296 dtrace's printf() misses a corner case
6235357 dtrace(1M) can't ignore SIGINT and SIGTERM
6282866 D string behaviors need some cleanup
6304467 dtrace -G by itself does nothing and produces no output
6305443 dtrace falls for typedef fake
6312329 qlen.d example won't parse
6312678 D compiler needs to resolve direct_declarator IDENT/TNAME ambiguity
6320980 ctf_enum_value() returns NULL instead of CTF_ERR on failure
6327910 req.flg entry missing for usr/src/common/smbios
6335522 smbios_bufopen() computes intermediate checksum using unpacked header
6335549 prtdiag: can't get smbios tables on toshiba tecra s1 laptop
6335559 smbios utility reports bogus cache size information
6368524 ctf_lookup_by_name() qualifier check can be made more efficient
6368526 fmd -o debug=help core dumps after printing help message
6368529 Psetbkpt() is returning EBUSY instead of setting errno to EBUSY
Diffstat (limited to 'usr/src/common/ctf')
| -rw-r--r-- | usr/src/common/ctf/ctf_create.c | 219 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_hash.c | 21 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_impl.h | 11 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_lookup.c | 42 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_open.c | 104 | ||||
| -rw-r--r-- | usr/src/common/ctf/ctf_types.c | 9 |
6 files changed, 266 insertions, 140 deletions
diff --git a/usr/src/common/ctf/ctf_create.c b/usr/src/common/ctf/ctf_create.c index 0fcdd75566..a4f3df34e8 100644 --- a/usr/src/common/ctf/ctf_create.c +++ b/usr/src/common/ctf/ctf_create.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -51,9 +52,14 @@ ctf_create(int *errp) { static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } }; + const ulong_t hashlen = 128; + ctf_dtdef_t **hash = ctf_alloc(hashlen * sizeof (ctf_dtdef_t *)); ctf_sect_t cts; ctf_file_t *fp; + if (hash == NULL) + return (ctf_set_open_errno(errp, EAGAIN)); + cts.cts_name = _CTF_SECTION; cts.cts_type = SHT_PROGBITS; cts.cts_flags = 0; @@ -62,13 +68,19 @@ ctf_create(int *errp) cts.cts_entsize = 1; cts.cts_offset = 0; - if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) != NULL) { - fp->ctf_flags |= LCTF_RDWR; - fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE); - fp->ctf_dtnextid = 1; - fp->ctf_dtoldid = 0; + if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) == NULL) { + ctf_free(hash, hashlen * sizeof (ctf_dtdef_t *)); + return (NULL); } + fp->ctf_flags |= LCTF_RDWR; + fp->ctf_dthashlen = hashlen; + bzero(hash, hashlen * sizeof (ctf_dtdef_t *)); + fp->ctf_dthash = hash; + fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE); + fp->ctf_dtnextid = 1; + fp->ctf_dtoldid = 0; + return (fp); } @@ -371,13 +383,18 @@ ctf_update(ctf_file_t *fp) nfp->ctf_refcnt = fp->ctf_refcnt; nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY; nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */ + nfp->ctf_dthash = fp->ctf_dthash; + nfp->ctf_dthashlen = fp->ctf_dthashlen; nfp->ctf_dtdefs = fp->ctf_dtdefs; nfp->ctf_dtstrlen = fp->ctf_dtstrlen; nfp->ctf_dtnextid = fp->ctf_dtnextid; nfp->ctf_dtoldid = fp->ctf_dtnextid - 1; nfp->ctf_specific = fp->ctf_specific; + fp->ctf_dthash = NULL; + fp->ctf_dthashlen = 0; bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t)); + bcopy(fp, &ofp, sizeof (ctf_file_t)); bcopy(nfp, fp, sizeof (ctf_file_t)); bcopy(&ofp, nfp, sizeof (ctf_file_t)); @@ -398,6 +415,82 @@ ctf_update(ctf_file_t *fp) return (0); } +void +ctf_dtd_insert(ctf_file_t *fp, ctf_dtdef_t *dtd) +{ + ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1); + + dtd->dtd_hash = fp->ctf_dthash[h]; + fp->ctf_dthash[h] = dtd; + ctf_list_append(&fp->ctf_dtdefs, dtd); +} + +void +ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd) +{ + ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1); + ctf_dtdef_t *p, **q = &fp->ctf_dthash[h]; + ctf_dmdef_t *dmd, *nmd; + size_t len; + + for (p = *q; p != NULL; p = p->dtd_hash) { + if (p != dtd) + q = &p->dtd_hash; + else + break; + } + + if (p != NULL) + *q = p->dtd_hash; + + switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) { + case CTF_K_STRUCT: + case CTF_K_UNION: + case CTF_K_ENUM: + for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); + dmd != NULL; dmd = nmd) { + if (dmd->dmd_name != NULL) { + len = strlen(dmd->dmd_name) + 1; + ctf_free(dmd->dmd_name, len); + fp->ctf_dtstrlen -= len; + } + nmd = ctf_list_next(dmd); + ctf_free(dmd, sizeof (ctf_dmdef_t)); + } + break; + case CTF_K_FUNCTION: + ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) * + CTF_INFO_VLEN(dtd->dtd_data.ctt_info)); + break; + } + + if (dtd->dtd_name) { + len = strlen(dtd->dtd_name) + 1; + ctf_free(dtd->dtd_name, len); + fp->ctf_dtstrlen -= len; + } + + ctf_list_delete(&fp->ctf_dtdefs, dtd); + ctf_free(dtd, sizeof (ctf_dtdef_t)); +} + +ctf_dtdef_t * +ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type) +{ + ulong_t h = type & (fp->ctf_dthashlen - 1); + ctf_dtdef_t *dtd; + + if (fp->ctf_dthash == NULL) + return (NULL); + + for (dtd = fp->ctf_dthash[h]; dtd != NULL; dtd = dtd->dtd_hash) { + if (dtd->dtd_type == type) + break; + } + + return (dtd); +} + /* * Discard all of the dynamic type definitions that have been added to the * container since the last call to ctf_update(). We locate such types by @@ -408,8 +501,6 @@ int ctf_discard(ctf_file_t *fp) { ctf_dtdef_t *dtd, *ntd; - ctf_dmdef_t *dmd, *nmd; - size_t len; if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); @@ -421,36 +512,8 @@ ctf_discard(ctf_file_t *fp) if (dtd->dtd_type <= fp->ctf_dtoldid) continue; /* skip types that have been committed */ - switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) { - case CTF_K_STRUCT: - case CTF_K_UNION: - case CTF_K_ENUM: - for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); - dmd != NULL; dmd = nmd) { - if (dmd->dmd_name != NULL) { - len = strlen(dmd->dmd_name) + 1; - ctf_free(dmd->dmd_name, len); - fp->ctf_dtstrlen -= len; - } - nmd = ctf_list_next(dmd); - ctf_free(dmd, sizeof (ctf_dmdef_t)); - } - break; - case CTF_K_FUNCTION: - ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) * - CTF_INFO_VLEN(dtd->dtd_data.ctt_info)); - break; - } - - if (dtd->dtd_name) { - len = strlen(dtd->dtd_name) + 1; - ctf_free(dtd->dtd_name, len); - fp->ctf_dtstrlen -= len; - } - ntd = ctf_list_next(dtd); - ctf_list_delete(&fp->ctf_dtdefs, dtd); - ctf_free(dtd, sizeof (ctf_dtdef_t)); + ctf_dtd_delete(fp, dtd); } fp->ctf_dtnextid = fp->ctf_dtoldid + 1; @@ -493,7 +556,7 @@ ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp) if (s != NULL) fp->ctf_dtstrlen += strlen(s) + 1; - ctf_list_append(&fp->ctf_dtdefs, dtd); + ctf_dtd_insert(fp, dtd); fp->ctf_flags |= LCTF_DIRTY; *rp = dtd; @@ -599,17 +662,11 @@ ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp) int ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp) { - ctf_dtdef_t *dtd; + ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type); if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); - for (dtd = ctf_list_next(&fp->ctf_dtdefs); - dtd != NULL; dtd = ctf_list_next(dtd)) { - if (dtd->dtd_type == type) - break; - } - if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY) return (ctf_set_errno(fp, ECTF_BADID)); @@ -661,36 +718,61 @@ ctf_add_function(ctf_file_t *fp, uint_t flag, ctf_id_t ctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name) { + ctf_hash_t *hp = &fp->ctf_structs; + ctf_helem_t *hep = NULL; ctf_dtdef_t *dtd; ctf_id_t type; - if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) + if (name != NULL) + hep = ctf_hash_lookup(hp, fp, name, strlen(name)); + + if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) + dtd = ctf_dtd_lookup(fp, type = hep->h_type); + else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, flag, 0); + dtd->dtd_data.ctt_size = 0; + return (type); } ctf_id_t ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name) { + ctf_hash_t *hp = &fp->ctf_unions; + ctf_helem_t *hep = NULL; ctf_dtdef_t *dtd; ctf_id_t type; - if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) + if (name != NULL) + hep = ctf_hash_lookup(hp, fp, name, strlen(name)); + + if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) + dtd = ctf_dtd_lookup(fp, type = hep->h_type); + else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, flag, 0); + dtd->dtd_data.ctt_size = 0; + return (type); } ctf_id_t ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name) { + ctf_hash_t *hp = &fp->ctf_enums; + ctf_helem_t *hep = NULL; ctf_dtdef_t *dtd; ctf_id_t type; - if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) + if (name != NULL) + hep = ctf_hash_lookup(hp, fp, name, strlen(name)); + + if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD) + dtd = ctf_dtd_lookup(fp, type = hep->h_type); + else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0); @@ -702,16 +784,39 @@ ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name) ctf_id_t ctf_add_forward(ctf_file_t *fp, uint_t flag, const char *name, uint_t kind) { + ctf_hash_t *hp; + ctf_helem_t *hep; ctf_dtdef_t *dtd; ctf_id_t type; - if (kind != CTF_K_STRUCT && kind != CTF_K_UNION && kind != CTF_K_ENUM) + switch (kind) { + case CTF_K_STRUCT: + hp = &fp->ctf_structs; + break; + case CTF_K_UNION: + hp = &fp->ctf_unions; + break; + case CTF_K_ENUM: + hp = &fp->ctf_enums; + break; + default: return (ctf_set_errno(fp, ECTF_NOTSUE)); + } + + /* + * If the type is already defined or exists as a forward tag, just + * return the ctf_id_t of the existing definition. + */ + if (name != NULL && (hep = ctf_hash_lookup(hp, + fp, name, strlen(name))) != NULL) + return (hep->h_type); if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR) return (CTF_ERR); /* errno is set for us */ dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, flag, 0); + dtd->dtd_data.ctt_type = kind; + return (type); } @@ -754,7 +859,7 @@ ctf_add_restrict(ctf_file_t *fp, uint_t flag, ctf_id_t ref) int ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value) { - ctf_dtdef_t *dtd; + ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, enid); ctf_dmdef_t *dmd; uint_t kind, vlen, root; @@ -766,12 +871,6 @@ ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value) if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); - for (dtd = ctf_list_next(&fp->ctf_dtdefs); - dtd != NULL; dtd = ctf_list_next(dtd)) { - if (dtd->dtd_type == enid) - break; - } - if (dtd == NULL) return (ctf_set_errno(fp, ECTF_BADID)); @@ -816,7 +915,7 @@ ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value) int ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type) { - ctf_dtdef_t *dtd; + ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid); ctf_dmdef_t *dmd; ssize_t msize, malign, ssize; @@ -826,12 +925,6 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type) if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno(fp, ECTF_RDONLY)); - for (dtd = ctf_list_next(&fp->ctf_dtdefs); - dtd != NULL; dtd = ctf_list_next(dtd)) { - if (dtd->dtd_type == souid) - break; - } - if (dtd == NULL) return (ctf_set_errno(fp, ECTF_BADID)); diff --git a/usr/src/common/ctf/ctf_hash.c b/usr/src/common/ctf/ctf_hash.c index ff2ba61352..b10a7618f6 100644 --- a/usr/src/common/ctf/ctf_hash.c +++ b/usr/src/common/ctf/ctf_hash.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -122,6 +123,24 @@ ctf_hash_insert(ctf_hash_t *hp, ctf_file_t *fp, ushort_t type, uint_t name) return (0); } +/* + * Wrapper for ctf_hash_lookup/ctf_hash_insert: if the key is already in the + * hash, override the previous definition with this new official definition. + * If the key is not present, then call ctf_hash_insert() and hash it in. + */ +int +ctf_hash_define(ctf_hash_t *hp, ctf_file_t *fp, ushort_t type, uint_t name) +{ + const char *str = ctf_strptr(fp, name); + ctf_helem_t *hep = ctf_hash_lookup(hp, fp, str, strlen(str)); + + if (hep == NULL) + return (ctf_hash_insert(hp, fp, type, name)); + + hep->h_type = type; + return (0); +} + ctf_helem_t * ctf_hash_lookup(ctf_hash_t *hp, ctf_file_t *fp, const char *key, size_t len) { diff --git a/usr/src/common/ctf/ctf_impl.h b/usr/src/common/ctf/ctf_impl.h index e56dbdff31..99990806a3 100644 --- a/usr/src/common/ctf/ctf_impl.h +++ b/usr/src/common/ctf/ctf_impl.h @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -144,6 +145,7 @@ typedef struct ctf_dmdef { typedef struct ctf_dtdef { ctf_list_t dtd_list; /* list forward/back pointers */ + struct ctf_dtdef *dtd_hash; /* hash chain pointer for ctf_dthash */ char *dtd_name; /* name associated with definition (if any) */ ctf_id_t dtd_type; /* type identifier for this definition */ ctf_type_t dtd_data; /* type node (see <sys/ctf.h>) */ @@ -200,6 +202,8 @@ struct ctf_file { uint_t ctf_flags; /* libctf flags (see below) */ int ctf_errno; /* error code for most recent error */ int ctf_version; /* CTF data version */ + ctf_dtdef_t **ctf_dthash; /* hash of dynamic type definitions */ + ulong_t ctf_dthashlen; /* size of dynamic type hash bucket array */ ctf_list_t ctf_dtdefs; /* list of dynamic type definitions */ size_t ctf_dtstrlen; /* total length of dynamic type strings */ ulong_t ctf_dtnextid; /* next dynamic type id to assign */ @@ -275,6 +279,7 @@ extern const ctf_type_t *ctf_lookup_by_id(ctf_file_t **, ctf_id_t); extern int ctf_hash_create(ctf_hash_t *, ulong_t); extern int ctf_hash_insert(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t); +extern int ctf_hash_define(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t); extern ctf_helem_t *ctf_hash_lookup(ctf_hash_t *, ctf_file_t *, const char *, size_t); extern uint_t ctf_hash_size(const ctf_hash_t *); @@ -287,6 +292,10 @@ extern void ctf_list_append(ctf_list_t *, void *); extern void ctf_list_prepend(ctf_list_t *, void *); extern void ctf_list_delete(ctf_list_t *, void *); +extern void ctf_dtd_insert(ctf_file_t *, ctf_dtdef_t *); +extern void ctf_dtd_delete(ctf_file_t *, ctf_dtdef_t *); +extern ctf_dtdef_t *ctf_dtd_lookup(ctf_file_t *, ctf_id_t); + extern void ctf_decl_init(ctf_decl_t *, char *, size_t); extern void ctf_decl_fini(ctf_decl_t *); extern void ctf_decl_push(ctf_decl_t *, ctf_file_t *, ctf_id_t); diff --git a/usr/src/common/ctf/ctf_lookup.c b/usr/src/common/ctf/ctf_lookup.c index 4285c74d92..f8fa724355 100644 --- a/usr/src/common/ctf/ctf_lookup.c +++ b/usr/src/common/ctf/ctf_lookup.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,7 +32,17 @@ /* * Compare the given input string and length against a table of known C storage - * qualifier keywords. We just ignore these in ctf_lookup_by_name, below. + * qualifier keywords. We just ignore these in ctf_lookup_by_name, below. To + * do this quickly, we use a pre-computed Perfect Hash Function similar to the + * technique originally described in the classic paper: + * + * R.J. Cichelli, "Minimal Perfect Hash Functions Made Simple", + * Communications of the ACM, Volume 23, Issue 1, January 1980, pp. 17-19. + * + * For an input string S of length N, we use hash H = S[N - 1] + N - 105, which + * for the current set of qualifiers yields a unique H in the range [0 .. 20]. + * The hash can be modified when the keyword set changes as necessary. We also + * store the length of each keyword and check it prior to the final strcmp(). */ static int isqualifier(const char *s, size_t len) @@ -39,26 +50,19 @@ isqualifier(const char *s, size_t len) static const struct qual { const char *q_name; size_t q_len; - } q[] = { - { "auto", 4 }, - { "const", 5 }, - { "extern", 6 }, - { "register", 8 }, - { "restrict", 8 }, - { "_Restrict", 9 }, - { "static", 6 }, - { "volatile", 8 }, - { NULL, 0 } + } qhash[] = { + { "static", 6 }, { "", 0 }, { "", 0 }, { "", 0 }, + { "volatile", 8 }, { "", 0 }, { "", 0 }, { "", 0 }, { "", 0 }, + { "", 0 }, { "auto", 4 }, { "extern", 6 }, { "", 0 }, { "", 0 }, + { "", 0 }, { "", 0 }, { "const", 5 }, { "register", 8 }, + { "", 0 }, { "restrict", 8 }, { "_Restrict", 9 } }; - int i; + int h = s[len - 1] + (int)len - 105; + const struct qual *qp = &qhash[h]; - for (i = 0; q[i].q_name != NULL; i++) { - if (len == q[i].q_len && strncmp(s, q[i].q_name, len) == 0) - return (1); - } - - return (0); + return (h >= 0 && h < sizeof (qhash) / sizeof (qhash[0]) && + len == qp->q_len && strncmp(qp->q_name, s, qp->q_len) == 0); } /* diff --git a/usr/src/common/ctf/ctf_open.c b/usr/src/common/ctf/ctf_open.c index b37e0a0797..e49a4cb329 100644 --- a/usr/src/common/ctf/ctf_open.c +++ b/usr/src/common/ctf/ctf_open.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -195,15 +196,16 @@ init_symtab(ctf_file_t *fp, const ctf_header_t *hp, * and initialize the hash tables of each named type. */ static int -init_types(ctf_file_t *fp, const ctf_header_t *hp) +init_types(ctf_file_t *fp, const ctf_header_t *cth) { /* LINTED - pointer alignment */ - const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + hp->cth_typeoff); + const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + cth->cth_typeoff); /* LINTED - pointer alignment */ - const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + hp->cth_stroff); + const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + cth->cth_stroff); ulong_t pop[CTF_K_MAX + 1] = { 0 }; const ctf_type_t *tp; + ctf_hash_t *hp; ushort_t id, dst; uint_t *xp; @@ -213,7 +215,7 @@ init_types(ctf_file_t *fp, const ctf_header_t *hp) * date cth_parname, we also scan the types themselves for references * to values in the range reserved for child types in our first pass. */ - int child = hp->cth_parname != 0; + int child = cth->cth_parname != 0; int nlstructs = 0, nlunions = 0; int err; @@ -266,6 +268,17 @@ init_types(ctf_file_t *fp, const ctf_header_t *hp) vbytes = sizeof (ctf_enum_t) * vlen; break; case CTF_K_FORWARD: + /* + * For forward declarations, ctt_type is the CTF_K_* + * kind for the tag, so bump that population count too. + * If ctt_type is unknown, treat the tag as a struct. + */ + if (tp->ctt_type == CTF_K_UNKNOWN || + tp->ctt_type >= CTF_K_MAX) + pop[CTF_K_STRUCT]++; + else + pop[tp->ctt_type]++; + /*FALLTHRU*/ case CTF_K_UNKNOWN: vbytes = 0; break; @@ -299,8 +312,7 @@ init_types(ctf_file_t *fp, const ctf_header_t *hp) * Now that we've counted up the number of each type, we can allocate * the hash tables, type translation table, and pointer table. */ - if ((err = ctf_hash_create(&fp->ctf_structs, - pop[CTF_K_STRUCT] + pop[CTF_K_FORWARD])) != 0) + if ((err = ctf_hash_create(&fp->ctf_structs, pop[CTF_K_STRUCT])) != 0) return (err); if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0) @@ -382,18 +394,11 @@ init_types(ctf_file_t *fp, const ctf_header_t *hp) break; case CTF_K_STRUCT: - /* - * If a struct's name is already present as a forward - * tag, then replace the tag with the struct definition. - */ - if ((hep = ctf_hash_lookup(&fp->ctf_structs, fp, - name, strlen(name))) == NULL) { - err = ctf_hash_insert(&fp->ctf_structs, fp, - CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); - if (err != 0 && err != ECTF_STRTAB) - return (err); - } else - hep->h_type = CTF_INDEX_TO_TYPE(id, child); + err = ctf_hash_define(&fp->ctf_structs, fp, + CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); + + if (err != 0 && err != ECTF_STRTAB) + return (err); if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) @@ -405,8 +410,9 @@ init_types(ctf_file_t *fp, const ctf_header_t *hp) break; case CTF_K_UNION: - err = ctf_hash_insert(&fp->ctf_unions, fp, + err = ctf_hash_define(&fp->ctf_unions, fp, CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); + if (err != 0 && err != ECTF_STRTAB) return (err); @@ -420,10 +426,12 @@ init_types(ctf_file_t *fp, const ctf_header_t *hp) break; case CTF_K_ENUM: - err = ctf_hash_insert(&fp->ctf_enums, fp, + err = ctf_hash_define(&fp->ctf_enums, fp, CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); + if (err != 0 && err != ECTF_STRTAB) return (err); + vbytes = sizeof (ctf_enum_t) * vlen; break; @@ -437,12 +445,26 @@ init_types(ctf_file_t *fp, const ctf_header_t *hp) case CTF_K_FORWARD: /* - * Only insert forward tags into the struct hash if the - * struct or tag name is not already present. + * Only insert forward tags into the given hash if the + * type or tag name is not already present. */ - if (ctf_hash_lookup(&fp->ctf_structs, fp, + switch (tp->ctt_type) { + case CTF_K_STRUCT: + hp = &fp->ctf_structs; + break; + case CTF_K_UNION: + hp = &fp->ctf_unions; + break; + case CTF_K_ENUM: + hp = &fp->ctf_enums; + break; + default: + hp = &fp->ctf_structs; + } + + if (ctf_hash_lookup(hp, fp, name, strlen(name)) == NULL) { - err = ctf_hash_insert(&fp->ctf_structs, fp, + err = ctf_hash_insert(hp, fp, CTF_INDEX_TO_TYPE(id, child), tp->ctt_name); if (err != 0 && err != ECTF_STRTAB) return (err); @@ -774,7 +796,6 @@ void ctf_close(ctf_file_t *fp) { ctf_dtdef_t *dtd, *ntd; - ctf_dmdef_t *dmd, *nmd; if (fp == NULL) return; /* allow ctf_close(NULL) to simplify caller code */ @@ -786,36 +807,15 @@ ctf_close(ctf_file_t *fp) return; } - for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { - switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) { - case CTF_K_STRUCT: - case CTF_K_UNION: - case CTF_K_ENUM: - for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members); - dmd != NULL; dmd = nmd) { - if (dmd->dmd_name != NULL) { - ctf_free(dmd->dmd_name, - strlen(dmd->dmd_name) + 1); - } - nmd = ctf_list_next(dmd); - ctf_free(dmd, sizeof (ctf_dmdef_t)); - } - break; - case CTF_K_FUNCTION: - ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) * - CTF_INFO_VLEN(dtd->dtd_data.ctt_info)); - break; - } - - if (dtd->dtd_name != NULL) - ctf_free(dtd->dtd_name, strlen(dtd->dtd_name) + 1); + if (fp->ctf_parent != NULL) + ctf_close(fp->ctf_parent); + for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) { ntd = ctf_list_next(dtd); - ctf_free(dtd, sizeof (ctf_dtdef_t)); + ctf_dtd_delete(fp, dtd); } - if (fp->ctf_parent != NULL) - ctf_close(fp->ctf_parent); + ctf_free(fp->ctf_dthash, fp->ctf_dthashlen * sizeof (ctf_dtdef_t *)); if (fp->ctf_flags & LCTF_MMAP) { if (fp->ctf_data.cts_data != NULL) diff --git a/usr/src/common/ctf/ctf_types.c b/usr/src/common/ctf/ctf_types.c index 401dccd871..290c518ae7 100644 --- a/usr/src/common/ctf/ctf_types.c +++ b/usr/src/common/ctf/ctf_types.c @@ -19,8 +19,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -747,14 +748,14 @@ ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp) uint_t n; if ((type = ctf_type_resolve(fp, type)) == CTF_ERR) - return (NULL); /* errno is set for us */ + return (CTF_ERR); /* errno is set for us */ if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) - return (NULL); /* errno is set for us */ + return (CTF_ERR); /* errno is set for us */ if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) { (void) ctf_set_errno(ofp, ECTF_NOTENUM); - return (NULL); + return (CTF_ERR); } (void) ctf_get_ctt_size(fp, tp, &size, &increment); |
