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/ctf_create.c | |
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/ctf_create.c')
-rw-r--r-- | usr/src/common/ctf/ctf_create.c | 219 |
1 files changed, 156 insertions, 63 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)); |