X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=libctf%2Fctf-types.c;h=cd910434ea41abcf72bdee6c19b5d8b9f22cd05b;hb=7a77f1ac2c6f899faa39e8c0b42d4284d586c44e;hp=a7fe5d0b184525d3290915892597979e81396e89;hpb=316afdb130346e44622229793d1fb8d391059f8d;p=deliverable%2Fbinutils-gdb.git diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index a7fe5d0b18..cd910434ea 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -1,5 +1,5 @@ /* Type handling functions. - Copyright (C) 2019 Free Software Foundation, Inc. + Copyright (C) 2019-2020 Free Software Foundation, Inc. This file is part of libctf. @@ -42,15 +42,16 @@ ctf_member_iter (ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg) { ctf_file_t *ofp = fp; const ctf_type_t *tp; + ctf_dtdef_t *dtd; ssize_t size, increment; uint32_t kind, n; int rc; if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ (void) ctf_get_ctt_size (fp, tp, &size, &increment); kind = LCTF_INFO_KIND (fp, tp->ctt_info); @@ -58,29 +59,43 @@ ctf_member_iter (ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg) if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) return (ctf_set_errno (ofp, ECTF_NOTSOU)); - if (size < CTF_LSTRUCT_THRESH) + if ((dtd = ctf_dynamic_type (fp, type)) == NULL) { - const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp + - increment); - - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++) + if (size < CTF_LSTRUCT_THRESH) { - const char *name = ctf_strptr (fp, mp->ctm_name); - if ((rc = func (name, mp->ctm_type, mp->ctm_offset, arg)) != 0) + const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp + + increment); + + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++) + { + const char *name = ctf_strptr (fp, mp->ctm_name); + if ((rc = func (name, mp->ctm_type, mp->ctm_offset, arg)) != 0) return rc; + } } + else + { + const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp + + increment); + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++) + { + const char *name = ctf_strptr (fp, lmp->ctlm_name); + if ((rc = func (name, lmp->ctlm_type, + (unsigned long) CTF_LMEM_OFFSET (lmp), arg)) != 0) + return rc; + } + } } else { - const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp + - increment); + ctf_dmdef_t *dmd; - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++) + for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + dmd != NULL; dmd = ctf_list_next (dmd)) { - const char *name = ctf_strptr (fp, lmp->ctlm_name); - if ((rc = func (name, lmp->ctlm_type, - (unsigned long) CTF_LMEM_OFFSET (lmp), arg)) != 0) + if ((rc = func (dmd->dmd_name, dmd->dmd_type, + dmd->dmd_offset, arg)) != 0) return rc; } } @@ -97,28 +112,43 @@ ctf_enum_iter (ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg) ctf_file_t *ofp = fp; const ctf_type_t *tp; const ctf_enum_t *ep; + ctf_dtdef_t *dtd; ssize_t increment; uint32_t n; int rc; if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM) return (ctf_set_errno (ofp, ECTF_NOTENUM)); (void) ctf_get_ctt_size (fp, tp, NULL, &increment); - ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); + if ((dtd = ctf_dynamic_type (ofp, type)) == NULL) + { + ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + { + const char *name = ctf_strptr (fp, ep->cte_name); + if ((rc = func (name, ep->cte_value, arg)) != 0) + return rc; + } + } + else { - const char *name = ctf_strptr (fp, ep->cte_name); - if ((rc = func (name, ep->cte_value, arg)) != 0) - return rc; + ctf_dmdef_t *dmd; + + for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + dmd != NULL; dmd = ctf_list_next (dmd)) + { + if ((rc = func (dmd->dmd_name, dmd->dmd_value, arg)) != 0) + return rc; + } } return 0; @@ -144,22 +174,57 @@ ctf_type_iter (ctf_file_t *fp, ctf_type_f *func, void *arg) return 0; } +/* Iterate over every type in the given CTF container, user-visible or not. + We pass the type ID of each type to the specified callback function. */ + +int +ctf_type_iter_all (ctf_file_t *fp, ctf_type_all_f *func, void *arg) +{ + ctf_id_t id, max = fp->ctf_typemax; + int rc, child = (fp->ctf_flags & LCTF_CHILD); + + for (id = 1; id <= max; id++) + { + const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, id); + if ((rc = func (LCTF_INDEX_TO_TYPE (fp, id, child), + LCTF_INFO_ISROOT(fp, tp->ctt_info) + ? CTF_ADD_ROOT : CTF_ADD_NONROOT, arg) != 0)) + return rc; + } + + return 0; +} + /* Iterate over every variable in the given CTF container, in arbitrary order. We pass the name of each variable to the specified callback function. */ int ctf_variable_iter (ctf_file_t *fp, ctf_variable_f *func, void *arg) { - unsigned long i; int rc; if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL)) return ECTF_NOPARENT; - for (i = 0; i < fp->ctf_nvars; i++) - if ((rc = func (ctf_strptr (fp, fp->ctf_vars[i].ctv_name), - fp->ctf_vars[i].ctv_type, arg)) != 0) - return rc; + if (!(fp->ctf_flags & LCTF_RDWR)) + { + unsigned long i; + for (i = 0; i < fp->ctf_nvars; i++) + if ((rc = func (ctf_strptr (fp, fp->ctf_vars[i].ctv_name), + fp->ctf_vars[i].ctv_type, arg)) != 0) + return rc; + } + else + { + ctf_dvdef_t *dvd; + + for (dvd = ctf_list_next (&fp->ctf_dvdefs); dvd != NULL; + dvd = ctf_list_next (dvd)) + { + if ((rc = func (dvd->dvd_name, dvd->dvd_type, arg)) != 0) + return rc; + } + } return 0; } @@ -179,6 +244,9 @@ ctf_type_resolve (ctf_file_t *fp, ctf_id_t type) ctf_file_t *ofp = fp; const ctf_type_t *tp; + if (type == 0) + return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE)); + while ((tp = ctf_lookup_by_id (&fp, type)) != NULL) { switch (LCTF_INFO_KIND (fp, tp->ctt_info)) @@ -199,6 +267,8 @@ ctf_type_resolve (ctf_file_t *fp, ctf_id_t type) default: return type; } + if (type == 0) + return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE)); } return CTF_ERR; /* errno is set for us. */ @@ -223,6 +293,29 @@ ctf_type_resolve_unsliced (ctf_file_t *fp, ctf_id_t type) return type; } +/* Look up a name in the given name table, in the appropriate hash given the + kind of the identifier. The name is a raw, undecorated identifier. */ + +ctf_id_t ctf_lookup_by_rawname (ctf_file_t *fp, int kind, const char *name) +{ + return ctf_lookup_by_rawhash (fp, ctf_name_table (fp, kind), name); +} + +/* Look up a name in the given name table, in the appropriate hash given the + readability state of the dictionary. The name is a raw, undecorated + identifier. */ + +ctf_id_t ctf_lookup_by_rawhash (ctf_file_t *fp, ctf_names_t *np, const char *name) +{ + ctf_id_t id; + + if (fp->ctf_flags & LCTF_RDWR) + id = (ctf_id_t) ctf_dynhash_lookup (np->ctn_writable, name); + else + id = ctf_hash_lookup_type (np->ctn_readonly, fp, name); + return id; +} + /* Lookup the given type ID and return its name as a new dynamcally-allocated string. */ @@ -345,11 +438,12 @@ ssize_t ctf_type_lname (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len) { char *str = ctf_type_aname (fp, type); - size_t slen = strlen (str); + size_t slen; if (str == NULL) - return CTF_ERR; /* errno is set for us */ + return CTF_ERR; /* errno is set for us. */ + slen = strlen (str); snprintf (buf, len, "%s", str); free (str); @@ -369,6 +463,23 @@ ctf_type_name (ctf_file_t *fp, ctf_id_t type, char *buf, size_t len) return (rv >= 0 && (size_t) rv < len ? buf : NULL); } +/* Lookup the given type ID and return its raw, unadorned, undecorated name as a + new dynamcally-allocated string. */ + +char * +ctf_type_aname_raw (ctf_file_t *fp, ctf_id_t type) +{ + const ctf_type_t *tp; + + if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) + return NULL; /* errno is set for us. */ + + if (ctf_strraw (fp, tp->ctt_name) != NULL) + return strdup (ctf_strraw (fp, tp->ctt_name)); + + return NULL; +} + /* Resolve the type down to a base type node, and then return the size of the type storage in bytes. */ @@ -406,8 +517,8 @@ ctf_type_size (ctf_file_t *fp, ctf_id_t type) if ((size = ctf_get_ctt_size (fp, tp, NULL, NULL)) > 0) return size; - if (ctf_array_info (fp, type, &ar) == CTF_ERR - || (size = ctf_type_size (fp, ar.ctr_contents)) == CTF_ERR) + if (ctf_array_info (fp, type, &ar) < 0 + || (size = ctf_type_size (fp, ar.ctr_contents)) < 0) return -1; /* errno is set for us. */ return size * ar.ctr_nelems; @@ -445,7 +556,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type) case CTF_K_ARRAY: { ctf_arinfo_t r; - if (ctf_array_info (fp, type, &r) == CTF_ERR) + if (ctf_array_info (fp, type, &r) < 0) return -1; /* errno is set for us. */ return (ctf_type_align (fp, r.ctr_contents)); } @@ -474,7 +585,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type) for (; n != 0; n--, mp++) { ssize_t am = ctf_type_align (fp, mp->ctm_type); - align = MAX (align, am); + align = MAX (align, (size_t) am); } } else @@ -483,7 +594,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type) for (; n != 0; n--, lmp++) { ssize_t am = ctf_type_align (fp, lmp->ctlm_type); - align = MAX (align, am); + align = MAX (align, (size_t) am); } } } @@ -495,7 +606,7 @@ ctf_type_align (ctf_file_t *fp, ctf_id_t type) dmd != NULL; dmd = ctf_list_next (dmd)) { ssize_t am = ctf_type_align (fp, dmd->dmd_type); - align = MAX (align, am); + align = MAX (align, (size_t) am); if (kind == CTF_K_STRUCT) break; } @@ -520,7 +631,7 @@ ctf_type_kind_unsliced (ctf_file_t *fp, ctf_id_t type) const ctf_type_t *tp; if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ return (LCTF_INFO_KIND (fp, tp->ctt_info)); } @@ -533,13 +644,13 @@ ctf_type_kind (ctf_file_t *fp, ctf_id_t type) { int kind; - if ((kind = ctf_type_kind_unsliced (fp, type)) == CTF_ERR) - return CTF_ERR; + if ((kind = ctf_type_kind_unsliced (fp, type)) < 0) + return -1; if (kind == CTF_K_SLICE) { if ((type = ctf_type_reference (fp, type)) == CTF_ERR) - return CTF_ERR; + return -1; kind = ctf_type_kind_unsliced (fp, type); } @@ -624,11 +735,31 @@ ctf_type_encoding (ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep) uint32_t data; if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if ((dtd = ctf_dynamic_type (ofp, type)) != NULL) { - *ep = dtd->dtd_u.dtu_enc; + switch (LCTF_INFO_KIND (fp, tp->ctt_info)) + { + case CTF_K_INTEGER: + case CTF_K_FLOAT: + *ep = dtd->dtd_u.dtu_enc; + break; + case CTF_K_SLICE: + { + const ctf_slice_t *slice; + ctf_encoding_t underlying_en; + slice = &dtd->dtd_u.dtu_slice; + + data = ctf_type_encoding (fp, slice->cts_type, &underlying_en); + ep->cte_format = underlying_en.cte_format; + ep->cte_offset = slice->cts_offset; + ep->cte_bits = slice->cts_bits; + break; + } + default: + return (ctf_set_errno (ofp, ECTF_NOTINTFP)); + } return 0; } @@ -786,14 +917,15 @@ ctf_member_info (ctf_file_t *fp, ctf_id_t type, const char *name, { ctf_file_t *ofp = fp; const ctf_type_t *tp; + ctf_dtdef_t *dtd; ssize_t size, increment; uint32_t kind, n; if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ (void) ctf_get_ctt_size (fp, tp, &size, &increment); kind = LCTF_INFO_KIND (fp, tp->ctt_info); @@ -801,32 +933,50 @@ ctf_member_info (ctf_file_t *fp, ctf_id_t type, const char *name, if (kind != CTF_K_STRUCT && kind != CTF_K_UNION) return (ctf_set_errno (ofp, ECTF_NOTSOU)); - if (size < CTF_LSTRUCT_THRESH) + if ((dtd = ctf_dynamic_type (fp, type)) == NULL) { - const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp + - increment); + if (size < CTF_LSTRUCT_THRESH) + { + const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp + + increment); - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++) + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++) + { + if (strcmp (ctf_strptr (fp, mp->ctm_name), name) == 0) + { + mip->ctm_type = mp->ctm_type; + mip->ctm_offset = mp->ctm_offset; + return 0; + } + } + } + else { - if (strcmp (ctf_strptr (fp, mp->ctm_name), name) == 0) + const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp + + increment); + + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++) { - mip->ctm_type = mp->ctm_type; - mip->ctm_offset = mp->ctm_offset; - return 0; + if (strcmp (ctf_strptr (fp, lmp->ctlm_name), name) == 0) + { + mip->ctm_type = lmp->ctlm_type; + mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp); + return 0; + } } } } else { - const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp + - increment); + ctf_dmdef_t *dmd; - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++) + for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + dmd != NULL; dmd = ctf_list_next (dmd)) { - if (strcmp (ctf_strptr (fp, lmp->ctlm_name), name) == 0) + if (strcmp (dmd->dmd_name, name) == 0) { - mip->ctm_type = lmp->ctlm_type; - mip->ctm_offset = (unsigned long) CTF_LMEM_OFFSET (lmp); + mip->ctm_type = dmd->dmd_type; + mip->ctm_offset = dmd->dmd_offset; return 0; } } @@ -847,7 +997,7 @@ ctf_array_info (ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp) ssize_t increment; if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ARRAY) return (ctf_set_errno (ofp, ECTF_NOTARRAY)); @@ -877,6 +1027,7 @@ ctf_enum_name (ctf_file_t *fp, ctf_id_t type, int value) ctf_file_t *ofp = fp; const ctf_type_t *tp; const ctf_enum_t *ep; + const ctf_dtdef_t *dtd; ssize_t increment; uint32_t n; @@ -894,12 +1045,26 @@ ctf_enum_name (ctf_file_t *fp, ctf_id_t type, int value) (void) ctf_get_ctt_size (fp, tp, NULL, &increment); - ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); + if ((dtd = ctf_dynamic_type (ofp, type)) == NULL) + { + ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + { + if (ep->cte_value == value) + return (ctf_strptr (fp, ep->cte_name)); + } + } + else { - if (ep->cte_value == value) - return (ctf_strptr (fp, ep->cte_name)); + ctf_dmdef_t *dmd; + + for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + dmd != NULL; dmd = ctf_list_next (dmd)) + { + if (dmd->dmd_value == value) + return dmd->dmd_name; + } } (void) ctf_set_errno (ofp, ECTF_NOENUMNAM); @@ -915,37 +1080,132 @@ ctf_enum_value (ctf_file_t * fp, ctf_id_t type, const char *name, int *valp) ctf_file_t *ofp = fp; const ctf_type_t *tp; const ctf_enum_t *ep; + const ctf_dtdef_t *dtd; ssize_t increment; uint32_t n; if ((type = ctf_type_resolve_unsliced (fp, type)) == CTF_ERR) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if (LCTF_INFO_KIND (fp, tp->ctt_info) != CTF_K_ENUM) { (void) ctf_set_errno (ofp, ECTF_NOTENUM); - return CTF_ERR; + return -1; } (void) ctf_get_ctt_size (fp, tp, NULL, &increment); ep = (const ctf_enum_t *) ((uintptr_t) tp + increment); - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) + if ((dtd = ctf_dynamic_type (ofp, type)) == NULL) { - if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0) + for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++) { - if (valp != NULL) - *valp = ep->cte_value; - return 0; + if (strcmp (ctf_strptr (fp, ep->cte_name), name) == 0) + { + if (valp != NULL) + *valp = ep->cte_value; + return 0; + } + } + } + else + { + ctf_dmdef_t *dmd; + + for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + dmd != NULL; dmd = ctf_list_next (dmd)) + { + if (strcmp (dmd->dmd_name, name) == 0) + { + if (valp != NULL) + *valp = dmd->dmd_value; + return 0; + } } } (void) ctf_set_errno (ofp, ECTF_NOENUMNAM); - return CTF_ERR; + return -1; +} + +/* Given a type ID relating to a function type, return info on return types and + arg counts for that function. */ + +int +ctf_func_type_info (ctf_file_t *fp, ctf_id_t type, ctf_funcinfo_t *fip) +{ + const ctf_type_t *tp; + uint32_t kind; + const uint32_t *args; + const ctf_dtdef_t *dtd; + ssize_t size, increment; + + if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) + return -1; /* errno is set for us. */ + + 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); + kind = LCTF_INFO_KIND (fp, tp->ctt_info); + + if (kind != CTF_K_FUNCTION) + return (ctf_set_errno (fp, ECTF_NOTFUNC)); + + fip->ctc_return = tp->ctt_type; + fip->ctc_flags = 0; + fip->ctc_argc = LCTF_INFO_VLEN (fp, tp->ctt_info); + + if ((dtd = ctf_dynamic_type (fp, type)) == NULL) + args = (uint32_t *) ((uintptr_t) tp + increment); + else + args = (uint32_t *) dtd->dtd_u.dtu_argv; + + if (fip->ctc_argc != 0 && args[fip->ctc_argc - 1] == 0) + { + fip->ctc_flags |= CTF_FUNC_VARARG; + fip->ctc_argc--; + } + + return 0; +} + +/* Given a type ID relating to a function type,, return the arguments for the + function. */ + +int +ctf_func_type_args (ctf_file_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv) +{ + const ctf_type_t *tp; + const uint32_t *args; + const ctf_dtdef_t *dtd; + ssize_t size, increment; + ctf_funcinfo_t f; + + if (ctf_func_type_info (fp, type, &f) < 0) + return -1; /* errno is set for us. */ + + if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) + return -1; /* errno is set for us. */ + + 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); + + if ((dtd = ctf_dynamic_type (fp, type)) == NULL) + args = (uint32_t *) ((uintptr_t) tp + increment); + else + args = (uint32_t *) dtd->dtd_u.dtu_argv; + + for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--) + *argv++ = *args++; + + return 0; } /* Recursively visit the members of any type. This function is used as the @@ -960,15 +1220,16 @@ ctf_type_rvisit (ctf_file_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; ssize_t size, increment; uint32_t kind, n; int rc; if ((type = ctf_type_resolve (fp, type)) == CTF_ERR) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if ((tp = ctf_lookup_by_id (&fp, type)) == NULL) - return CTF_ERR; /* errno is set for us. */ + return -1; /* errno is set for us. */ if ((rc = func (name, otype, offset, depth, arg)) != 0) return rc; @@ -980,32 +1241,48 @@ ctf_type_rvisit (ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, (void) ctf_get_ctt_size (fp, tp, &size, &increment); - if (size < CTF_LSTRUCT_THRESH) + if ((dtd = ctf_dynamic_type (fp, type)) == NULL) { - const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp + - increment); - - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, mp++) + if (size < CTF_LSTRUCT_THRESH) { - 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; + const ctf_member_t *mp = (const ctf_member_t *) ((uintptr_t) tp + + increment); + + 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; + } } + else + { + const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp + + increment); + 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; + } + } } else { - const ctf_lmember_t *lmp = (const ctf_lmember_t *) ((uintptr_t) tp + - increment); + ctf_dmdef_t *dmd; - for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, lmp++) + for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); + dmd != NULL; dmd = ctf_list_next (dmd)) { - if ((rc = ctf_type_rvisit (fp, lmp->ctlm_type, - func, arg, ctf_strptr (fp, - lmp->ctlm_name), - offset + (unsigned long) CTF_LMEM_OFFSET (lmp), + if ((rc = ctf_type_rvisit (fp, dmd->dmd_type, func, arg, + dmd->dmd_name, dmd->dmd_offset, depth + 1)) != 0) return rc; }