diff options
-rw-r--r-- | libctf/ChangeLog | 12 | ||||
-rw-r--r-- | libctf/ctf-impl.h | 4 | ||||
-rw-r--r-- | libctf/ctf-types.c | 291 |
3 files changed, 150 insertions, 157 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog index 7874a77..85eb09d 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,5 +1,17 @@ 2021-03-18 Nick Alcock <nick.alcock@oracle.com> + * ctf-impl.h (ctf_next_t) <ctn_tp>: New. + <u.ctn_mp>: Remove. + <u.ctn_lmp>: Remove. + <u.ctn_vlen>: New. + * ctf-types.c (ctf_struct_member): New. + (ctf_member_next): Use it, dropping separate large/small code paths. + (ctf_type_align): Likewise. + (ctf_member_info): Likewise. + (ctf_type_rvisit): Likewise. + +2021-03-18 Nick Alcock <nick.alcock@oracle.com> + * ctf-impl.h (ctf_dtdef_t) <dtu_members>: Remove. <dtd_u>: Likewise. (ctf_dmdef_t): Remove. diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h index 87dd03b..ad4af32 100644 --- a/libctf/ctf-impl.h +++ b/libctf/ctf-impl.h @@ -530,6 +530,7 @@ struct ctf_next ctf_id_t ctn_type; ssize_t ctn_size; ssize_t ctn_increment; + const ctf_type_t *ctn_tp; uint32_t ctn_n; /* Some iterators contain other iterators, in addition to their other @@ -542,8 +543,7 @@ struct ctf_next members, and the structure, variable and enum members, etc. */ union { - const ctf_member_t *ctn_mp; - const ctf_lmember_t *ctn_lmp; + unsigned char *ctn_vlen; const ctf_enum_t *ctn_en; const ctf_dvdef_t *ctn_dvd; ctf_next_hkv_t *ctn_sorted_hkv; diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index df7673e..ed76eca 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -35,6 +35,36 @@ ctf_type_ischild (ctf_dict_t * fp, ctf_id_t id) return (LCTF_TYPE_ISCHILD (fp, id)); } +/* Expand a structure element into the passed-in ctf_lmember_t. */ + +static int +ctf_struct_member (ctf_dict_t *fp, ctf_lmember_t *dst, const ctf_type_t *tp, + unsigned char *vlen, size_t vbytes, size_t n) +{ + if (!ctf_assert (fp, n < LCTF_INFO_VLEN (fp, tp->ctt_info))) + return -1; /* errno is set for us. */ + + /* Already large. */ + if (tp->ctt_size == CTF_LSIZE_SENT) + { + ctf_lmember_t *lmp = (ctf_lmember_t *) vlen; + + if (!ctf_assert (fp, (n + 1) * sizeof (ctf_lmember_t) <= vbytes)) + return -1; /* errno is set for us. */ + + memcpy (dst, &lmp[n], sizeof (ctf_lmember_t)); + } + else + { + ctf_member_t *mp = (ctf_member_t *) vlen; + dst->ctlm_name = mp[n].ctm_name; + dst->ctlm_type = mp[n].ctm_type; + dst->ctlm_offsetlo = mp[n].ctm_offset; + dst->ctlm_offsethi = 0; + } + return 0; +} + /* 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. */ @@ -72,12 +102,14 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, ctf_dict_t *ofp = fp; uint32_t kind; ssize_t offset; + uint32_t max_vlen; ctf_next_t *i = *it; if (!i) { const ctf_type_t *tp; ctf_dtdef_t *dtd; + ssize_t size; ssize_t increment; if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) @@ -89,8 +121,9 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, if ((i = ctf_next_create ()) == NULL) return ctf_set_errno (ofp, ENOMEM); i->cu.ctn_fp = ofp; + i->ctn_tp = tp; - (void) ctf_get_ctt_size (fp, tp, &i->ctn_size, &increment); + ctf_get_ctt_size (fp, tp, &size, &increment); kind = LCTF_INFO_KIND (fp, tp->ctt_info); if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) @@ -99,20 +132,20 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, return (ctf_set_errno (ofp, ECTF_NOTSOU)); } - dtd = ctf_dynamic_type (fp, type); - i->ctn_iter_fun = (void (*) (void)) ctf_member_next; - i->ctn_n = LCTF_INFO_VLEN (fp, tp->ctt_info); - - if (dtd == NULL) + if ((dtd = ctf_dynamic_type (fp, type)) != NULL) { - if (i->ctn_size < CTF_LSTRUCT_THRESH) - i->u.ctn_mp = (const ctf_member_t *) ((uintptr_t) tp + increment); - else - i->u.ctn_lmp = (const ctf_lmember_t *) ((uintptr_t) tp + increment); + i->u.ctn_vlen = dtd->dtd_vlen; + i->ctn_size = dtd->dtd_vlen_alloc; } else - i->u.ctn_lmp = (const ctf_lmember_t *) dtd->dtd_vlen; + { + unsigned long vlen = LCTF_INFO_VLEN (fp, tp->ctt_info); + i->u.ctn_vlen = (unsigned char *) tp + increment; + i->ctn_size = LCTF_VBYTES (fp, kind, size, vlen);; + } + i->ctn_iter_fun = (void (*) (void)) ctf_member_next; + i->ctn_n = 0; *it = i; } @@ -126,6 +159,8 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, if ((fp = ctf_get_dict (ofp, type)) == NULL) return (ctf_set_errno (ofp, ECTF_NOPARENT)); + max_vlen = LCTF_INFO_VLEN (fp, i->ctn_tp->ctt_info); + /* When we hit an unnamed struct/union member, we set ctn_type to indicate that we are inside one, then return the unnamed member: on the next call, we must skip over top-level member iteration in favour of iteration within @@ -134,46 +169,29 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, retry: if (!i->ctn_type) { - if (i->ctn_n == 0) - goto end_iter; - - /* Dynamic structures in read-write dicts always use lmembers. */ - if (i->ctn_size < CTF_LSTRUCT_THRESH - && !(fp->ctf_flags & LCTF_RDWR)) - { - const char *membname = ctf_strptr (fp, i->u.ctn_mp->ctm_name); + ctf_lmember_t memb; + const char *membname; - if (name) - *name = membname; - if (membtype) - *membtype = i->u.ctn_mp->ctm_type; - offset = i->u.ctn_mp->ctm_offset; - - if (membname[0] == 0 - && (ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_STRUCT - || ctf_type_kind (fp, i->u.ctn_mp->ctm_type) == CTF_K_UNION)) - i->ctn_type = i->u.ctn_mp->ctm_type; + if (i->ctn_n == max_vlen) + goto end_iter; - i->u.ctn_mp++; - } - else - { - const char *membname = ctf_strptr (fp, i->u.ctn_lmp->ctlm_name); + if (ctf_struct_member (fp, &memb, i->ctn_tp, i->u.ctn_vlen, i->ctn_size, + i->ctn_n) < 0) + return -1; /* errno is set for us. */ - if (name) - *name = membname; - if (membtype) - *membtype = i->u.ctn_lmp->ctlm_type; - offset = (unsigned long) CTF_LMEM_OFFSET (i->u.ctn_lmp); + membname = ctf_strptr (fp, memb.ctlm_name); - if (membname[0] == 0 - && (ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_STRUCT - || ctf_type_kind (fp, i->u.ctn_lmp->ctlm_type) == CTF_K_UNION)) - i->ctn_type = i->u.ctn_lmp->ctlm_type; + if (name) + *name = membname; + if (membtype) + *membtype = memb.ctlm_type; + offset = (unsigned long) CTF_LMEM_OFFSET (&memb); - i->u.ctn_lmp++; - } - i->ctn_n--; + if (membname[0] == 0 + && (ctf_type_kind (fp, memb.ctlm_type) == CTF_K_STRUCT + || ctf_type_kind (fp, memb.ctlm_type) == CTF_K_UNION)) + i->ctn_type = memb.ctlm_type; + i->ctn_n++; /* The callers might want automatic recursive sub-struct traversal. */ if (!(flags & CTF_MN_RECURSE)) @@ -964,43 +982,36 @@ ctf_type_align (ctf_dict_t *fp, ctf_id_t type) case CTF_K_UNION: { size_t align = 0; - int dynamic = 0; ctf_dtdef_t *dtd; + unsigned char *vlen; + uint32_t i = 0, n = LCTF_INFO_VLEN (fp, tp->ctt_info); + ssize_t size, increment, vbytes; - if ((dtd = ctf_dynamic_type (ofp, type)) != NULL) - dynamic = 1; - - uint32_t n = LCTF_INFO_VLEN (fp, tp->ctt_info); - ssize_t size, increment; - const void *vmp; + ctf_get_ctt_size (fp, tp, &size, &increment); - (void) ctf_get_ctt_size (fp, tp, &size, &increment); - - if (!dynamic) - vmp = (unsigned char *) tp + increment; + if ((dtd = ctf_dynamic_type (fp, type)) != NULL) + { + vlen = dtd->dtd_vlen; + vbytes = dtd->dtd_vlen_alloc; + } else - vmp = dtd->dtd_vlen; + { + vlen = (unsigned char *) tp + increment; + vbytes = LCTF_VBYTES (fp, kind, size, n); + } if (kind == CTF_K_STRUCT) n = MIN (n, 1); /* Only use first member for structs. */ - if (size < CTF_LSTRUCT_THRESH && !dynamic) + for (; n != 0; n--, i++) { - const ctf_member_t *mp = vmp; - for (; n != 0; n--, mp++) - { - ssize_t am = ctf_type_align (ofp, mp->ctm_type); - align = MAX (align, (size_t) am); - } - } - else - { - const ctf_lmember_t *lmp = vmp; - for (; n != 0; n--, lmp++) - { - ssize_t am = ctf_type_align (ofp, lmp->ctlm_type); - align = MAX (align, (size_t) am); - } + ctf_lmember_t memb; + + if (ctf_struct_member (fp, &memb, tp, vlen, vbytes, i) < 0) + return -1; /* errno is set for us. */ + + ssize_t am = ctf_type_align (ofp, memb.ctlm_type); + align = MAX (align, (size_t) am); } return align; } @@ -1349,10 +1360,9 @@ ctf_member_info (ctf_dict_t *fp, ctf_id_t type, const char *name, ctf_dict_t *ofp = fp; const ctf_type_t *tp; ctf_dtdef_t *dtd; - const void *vmp; - ssize_t size, increment; - uint32_t kind, n; - int dynamic = 0; + unsigned char *vlen; + ssize_t size, increment, vbytes; + uint32_t kind, n, i = 0; if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) return -1; /* errno is set for us. */ @@ -1360,62 +1370,45 @@ ctf_member_info (ctf_dict_t *fp, ctf_id_t type, const char *name, if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) return -1; /* errno is set for us. */ - (void) ctf_get_ctt_size (fp, tp, &size, &increment); + ctf_get_ctt_size (fp, tp, &size, &increment); kind = LCTF_INFO_KIND (fp, tp->ctt_info); if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) return (ctf_set_errno (ofp, ECTF_NOTSOU)); - if ((dtd = ctf_dynamic_type (ofp, type)) != NULL) - dynamic = 1; - - if (!dynamic) - vmp = (unsigned char *) tp + increment; + n = LCTF_INFO_VLEN (fp, tp->ctt_info); + if ((dtd = ctf_dynamic_type (fp, type)) != NULL) + { + vlen = dtd->dtd_vlen; + vbytes = dtd->dtd_vlen_alloc; + } else - vmp = dtd->dtd_vlen; + { + vlen = (unsigned char *) tp + increment; + vbytes = LCTF_VBYTES (fp, kind, size, n); + } - if (size < CTF_LSTRUCT_THRESH && !dynamic) + for (; n != 0; n--, i++) { - const ctf_member_t *mp = vmp; + ctf_lmember_t memb; + const char *membname; - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++) - { - const char *membname = ctf_strptr (fp, mp->ctm_name); + if (ctf_struct_member (fp, &memb, tp, vlen, vbytes, i) < 0) + return -1; /* errno is set for us. */ - if (membname[0] == 0 - && (ctf_type_kind (fp, mp->ctm_type) == CTF_K_STRUCT - || ctf_type_kind (fp, mp->ctm_type) == CTF_K_UNION) - && (ctf_member_info (fp, mp->ctm_type, name, mip) == 0)) - return 0; + membname = ctf_strptr (fp, memb.ctlm_name); - if (strcmp (membname, name) == 0) - { - mip->ctm_type = mp->ctm_type; - mip->ctm_offset = mp->ctm_offset; - return 0; - } - } - } - else - { - const ctf_lmember_t *lmp = vmp; + if (membname[0] == 0 + && (ctf_type_kind (fp, memb.ctlm_type) == CTF_K_STRUCT + || ctf_type_kind (fp, memb.ctlm_type) == CTF_K_UNION) + && (ctf_member_info (fp, memb.ctlm_type, name, mip) == 0)) + return 0; - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++) + if (strcmp (membname, name) == 0) { - const char *membname = ctf_strptr (fp, lmp->ctlm_name); - - if (membname[0] == 0 - && (ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_STRUCT - || ctf_type_kind (fp, lmp->ctlm_type) == CTF_K_UNION) - && (ctf_member_info (fp, lmp->ctlm_type, name, mip) == 0)) - return 0; - - if (strcmp (membname, name) == 0) - { - mip->ctm_type = lmp->ctlm_type; - mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp); - return 0; - } + mip->ctm_type = memb.ctlm_type; + mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (&memb); + return 0; } } @@ -1630,10 +1623,9 @@ ctf_type_rvisit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func, ctf_id_t otype = type; const ctf_type_t *tp; const ctf_dtdef_t *dtd; - const void *vmp; - ssize_t size, increment; - uint32_t kind, n; - int dynamic = 0; + unsigned char *vlen; + ssize_t size, increment, vbytes; + uint32_t kind, n, i = 0; int rc; if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) @@ -1650,43 +1642,32 @@ ctf_type_rvisit (ctf_dict_t *fp, ctf_id_t type, ctf_visit_f *func, if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) return 0; - (void) ctf_get_ctt_size (fp, tp, &size, &increment); + ctf_get_ctt_size (fp, tp, &size, &increment); + n = LCTF_INFO_VLEN (fp, tp->ctt_info); if ((dtd = ctf_dynamic_type (fp, type)) != NULL) - dynamic = 1; - - if (!dynamic) - vmp = (unsigned char *) tp + increment; - else - vmp = dtd->dtd_vlen; - - if (size < CTF_LSTRUCT_THRESH && !dynamic) { - const ctf_member_t *mp = vmp; - - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++) - { - if ((rc = ctf_type_rvisit (fp, mp->ctm_type, - func, arg, ctf_strptr (fp, - mp->ctm_name), - offset + mp->ctm_offset, - depth + 1)) != 0) - return rc; - } + vlen = dtd->dtd_vlen; + vbytes = dtd->dtd_vlen_alloc; } else { - const ctf_lmember_t *lmp = vmp; + vlen = (unsigned char *) tp + increment; + vbytes = LCTF_VBYTES (fp, kind, size, n); + } - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++) - { - if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type, - func, arg, ctf_strptr (fp, - lmp->ctlm_name), - offset + (unsigned long) CTF_LMEM_OFFSET (lmp), - depth + 1)) != 0) - return rc; - } + for (; n != 0; n--, i++) + { + ctf_lmember_t memb; + + if (ctf_struct_member (fp, &memb, tp, vlen, vbytes, i) < 0) + return -1; /* errno is set for us. */ + + if ((rc = ctf_type_rvisit (fp, memb.ctlm_type, + func, arg, ctf_strptr (fp, memb.ctlm_name), + offset + (unsigned long) CTF_LMEM_OFFSET (&memb), + depth + 1)) != 0) + return rc; } return 0; |