From: Nick Alcock Date: Thu, 6 Nov 2025 13:43:50 +0000 (+0000) Subject: libctf, include, gdb: API review: delete ctf_*_iter X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d7cdbec228db950c39368fd4e4b29c09c3d2eafc;p=thirdparty%2Fbinutils-gdb.git libctf, include, gdb: API review: delete ctf_*_iter These functions are all redundant to the corresponding *_next function, are usually less pleasant to use, and are convertible into trivial while loops with very little effort. It's time to drop them. --- diff --git a/gdb/ctfread.c b/gdb/ctfread.c index 50ed21afe79..415d4e8c3df 100644 --- a/gdb/ctfread.c +++ b/gdb/ctfread.c @@ -183,7 +183,8 @@ struct ctf_per_tu_data /* Local function prototypes */ -static int ctf_add_type_cb (ctf_dict_t *fp, ctf_id_t tid, void *arg); +static void ctf_add_type_cb (ctf_dict_t *fp, ctf_id_t tid, + struct ctf_context *ccp); static struct type *read_array_type (struct ctf_context *cp, ctf_id_t tid); @@ -316,7 +317,7 @@ ctf_init_float_type (struct objfile *objfile, and ARG contains the ctf_field_info. */ static int -ctf_add_member_cb (ctf_dict_t *unused, +ctf_add_member_cb (ctf_dict_t *dict, const char *name, ctf_id_t tid, unsigned long offset, @@ -333,14 +334,14 @@ ctf_add_member_cb (ctf_dict_t *unused, fp = &new_field.field; fp->set_name (name); - kind = ctf_type_kind (ccp->dict, tid); + kind = ctf_type_kind (dict, tid); t = fetch_tid_type (ccp, tid); if (t == nullptr) { t = read_type_record (ccp, tid); if (t == nullptr) { - complaint (_("ctf_add_member_cb: %s has NO type (%ld)"), name, tid); + complaint (_("ctf_add_member_cb: %s has no type (%ld)"), name, tid); t = builtin_type (ccp->of)->builtin_error; set_tid_type (ccp->of, tid, t); } @@ -361,10 +362,9 @@ ctf_add_member_cb (ctf_dict_t *unused, /* Callback to add member NAME of EVAL to an enumeration type. ARG contains the ctf_field_info. */ -static int -ctf_add_enum_member_cb (const char *name, int64_t enum_value, void *arg) +static void +ctf_add_enum_member_cb (const char *name, int64_t enum_value, ctf_field_info *fip) { - struct ctf_field_info *fip = (struct ctf_field_info *) arg; struct ctf_nextfield new_field; struct field *fp; struct ctf_context *ccp = fip->cur_context; @@ -389,8 +389,6 @@ ctf_add_enum_member_cb (const char *name, int64_t enum_value, void *arg) } fip->fields.emplace_back (new_field); - - return 0; } /* Add a new type symbol entry, with its name from TID, its access @@ -562,10 +560,23 @@ process_struct_members (struct ctf_context *ccp, struct type *type) { struct ctf_field_info fi; + ctf_next_t *it = NULL; + const char *membname; + ctf_id_t membtype; + ssize_t offset; + int bit_width; fi.cur_context = ccp; - if (ctf_member_iter (ccp->dict, tid, ctf_add_member_cb, &fi) == CTF_ERR) - complaint (_("ctf_member_iter process_struct_members failed - %s"), + while ((offset = ctf_member_next (ccp->dict, tid, &it, &membname, &membtype, + &bit_width, 0)) >= 0) + { + if (ctf_add_member_cb (ccp->dict, membname, membtype, offset, bit_width, + &fi) < 0) + complaint (_("ctf_add_member_cb process_struct_members failed - %s"), + ctf_errmsg (ctf_errno (ccp->dict))); + } + if (ctf_errno (ccp->dict) != ECTF_NEXT_END) + complaint (_("process_struct_members iteration over members failed - %s"), ctf_errmsg (ctf_errno (ccp->dict))); /* Attach fields to the type. */ @@ -665,13 +676,19 @@ process_enum_type (struct ctf_context *ccp, ctf_id_t tid) { struct type *type; struct ctf_field_info fi; + ctf_next_t *it = NULL; + const char *name; + int64_t value; type = read_enum_type (ccp, tid); fi.cur_context = ccp; fi.ptype = type; - if (ctf_enum_iter (ccp->dict, tid, ctf_add_enum_member_cb, &fi) == CTF_ERR) - complaint (_("ctf_enum_iter process_enum_type failed - %s"), + while ((name = ctf_enum_next (ccp->dict, tid, &it, &value)) != NULL) + ctf_add_enum_member_cb (name, value, &fi); + + if (ctf_errno (ccp->dict) != ECTF_NEXT_END) + complaint (_("ctf_enum_next process_enum_type failed - %s"), ctf_errmsg (ctf_errno (ccp->dict))); /* Attach fields to the type. */ @@ -968,17 +985,16 @@ read_type_record (struct ctf_context *ccp, ctf_id_t tid) /* Callback to add type TID to the symbol table. */ -static int -ctf_add_type_cb (ctf_dict_t *fp, ctf_id_t tid, void *arg) +static void +ctf_add_type_cb (ctf_dict_t *fp, ctf_id_t tid, struct ctf_context *ccp) { - struct ctf_context *ccp = (struct ctf_context *) arg; struct type *type; uint32_t kind; /* Check if tid's type has already been defined. */ type = get_tid_type (ccp->of, tid); if (type != nullptr) - return 0; + return; ctf_id_t btid = ctf_type_reference (ccp->dict, tid); kind = ctf_type_kind (ccp->dict, tid); @@ -1027,16 +1043,14 @@ ctf_add_type_cb (ctf_dict_t *fp, ctf_id_t tid, void *arg) default: break; } - - return 0; } /* Callback to add variable NAME with TID to the symbol table. */ -static int -ctf_add_var_cb (ctf_dict_t *fp, const char *name, ctf_id_t id, void *arg) +static void +ctf_add_var_cb (ctf_dict_t *fp, const char *name, ctf_id_t id, + struct ctf_context *ccp) { - struct ctf_context *ccp = (struct ctf_context *) arg; struct symbol *sym = nullptr; struct type *type; uint32_t kind; @@ -1067,8 +1081,6 @@ ctf_add_var_cb (ctf_dict_t *fp, const char *name, ctf_id_t id, void *arg) add_symbol_to_list (sym, ccp->builder->get_global_symbols ()); set_symbol_address (ccp->of, sym, name); - - return 0; } /* Add entries in either data objects or function info section, controlled @@ -1204,20 +1216,28 @@ void ctf_psymtab::expand_psymtab (struct objfile *objfile) { struct ctf_context *ccp; + ctf_next_t *it = NULL; + ctf_id_t type; + const char *name; gdb_assert (!readin); ccp = &context; /* Iterate over entries in data types section. */ - if (ctf_type_iter (ccp->dict, ctf_add_type_cb, ccp) == CTF_ERR) - complaint (_("ctf_type_iter psymtab_to_symtab failed - %s"), - ctf_errmsg (ctf_errno (ccp->dict))); + while ((type = ctf_type_next (ccp->dict, &it, NULL, 0)) != CTF_ERR) + ctf_add_type_cb (ccp->dict, type, ccp); + if (ctf_errno (ccp->dict) != ECTF_NEXT_END) + complaint (_("ctf_type_next psymtab_to_symtab failed - %s"), + ctf_errmsg (ctf_errno (ccp->dict))); /* Iterate over entries in variable info section. */ - if (ctf_variable_iter (ccp->dict, ctf_add_var_cb, ccp) == CTF_ERR) - complaint (_("ctf_variable_iter psymtab_to_symtab failed - %s"), + while ((type = ctf_variable_next (ccp->dict, &it, &name)) != CTF_ERR) + ctf_add_var_cb (ccp->dict, name, type, ccp); + + if (ctf_errno (ccp->dict) != ECTF_NEXT_END) + complaint (_("ctf_variable_next psymtab_to_symtab failed - %s"), ctf_errmsg (ctf_errno (ccp->dict))); /* Add entries in data objects and function info sections. */ @@ -1303,15 +1323,12 @@ create_partial_symtab (const char *name, /* Callback to add type TID to partial symbol table. */ -static int -ctf_psymtab_type_cb (ctf_dict_t *fp, ctf_id_t tid, void *arg) +static void +ctf_psymtab_type_cb (ctf_dict_t *fp, ctf_id_t tid, struct ctf_context *ccp) { - struct ctf_context *ccp; uint32_t kind; int section = -1; - ccp = (struct ctf_context *) arg; - domain_enum domain = UNDEF_DOMAIN; location_class loc_class = LOC_UNDEF; kind = ctf_type_kind (ccp->dict, tid); @@ -1339,30 +1356,28 @@ ctf_psymtab_type_cb (ctf_dict_t *fp, ctf_id_t tid, void *arg) loc_class = LOC_TYPEDEF; break; case CTF_K_UNKNOWN: - return 0; + return; } const char *name = ctf_type_name_raw (ccp->dict, tid); if (name == nullptr || *name == '\0') - return 0; + return; ccp->pst->add_psymbol (name, false, domain, loc_class, section, psymbol_placement::GLOBAL, unrelocated_addr (0), language_c, ccp->partial_symtabs, ccp->of); - - return 0; } /* Callback to add variable NAME with ID to partial symbol table. */ -static int -ctf_psymtab_var_cb (ctf_dict_t *fp, const char *name, ctf_id_t id, void *arg) +static void +ctf_psymtab_var_cb (ctf_dict_t *fp, const char *name, ctf_id_t id, + struct ctf_context *ccp) { - struct ctf_context *ccp = (struct ctf_context *) arg; - uint32_t kind = ctf_type_kind (ccp->dict, id); + ccp->pst->add_psymbol (name, true, kind == CTF_K_FUNCTION ? FUNCTION_DOMAIN @@ -1371,7 +1386,6 @@ ctf_psymtab_var_cb (ctf_dict_t *fp, const char *name, ctf_id_t id, void *arg) psymbol_placement::GLOBAL, unrelocated_addr (0), language_c, ccp->partial_symtabs, ccp->of); - return 0; } /* Setup partial_symtab's describing each source file for which @@ -1383,6 +1397,9 @@ scan_partial_symbols (ctf_dict_t *dict, psymtab_storage *partial_symtabs, { struct objfile *of = tup->of; bool isparent = false; + ctf_next_t *it = NULL; + ctf_id_t type; + const char *name; if (strcmp (fname, ".ctf") == 0) { @@ -1397,12 +1414,18 @@ scan_partial_symbols (ctf_dict_t *dict, psymtab_storage *partial_symtabs, if (isparent == false) ccx->pst = pst; - if (ctf_type_iter (dict, ctf_psymtab_type_cb, ccx) == CTF_ERR) - complaint (_("ctf_type_iter scan_partial_symbols failed - %s"), + while ((type = ctf_type_next (dict, &it, NULL, 0)) != CTF_ERR) + ctf_psymtab_type_cb (dict, type, ccx); + + if (ctf_errno (dict) != ECTF_NEXT_END) + complaint (_("ctf_type_next scan_partial_symbols failed - %s"), ctf_errmsg (ctf_errno (dict))); - if (ctf_variable_iter (dict, ctf_psymtab_var_cb, ccx) == CTF_ERR) - complaint (_("ctf_variable_iter scan_partial_symbols failed - %s"), + while ((type = ctf_variable_next (dict, &it, &name)) != CTF_ERR) + ctf_psymtab_var_cb (dict, name, type, ccx); + + if (ctf_errno (dict) != ECTF_NEXT_END) + complaint (_("ctf_variable_next scan_partial_symbols failed - %s"), ctf_errmsg (ctf_errno (dict))); /* Scan CTF object and function sections which correspond to each @@ -1416,10 +1439,10 @@ scan_partial_symbols (ctf_dict_t *dict, psymtab_storage *partial_symtabs, /* Callback to build the psymtab for archive member NAME. */ -static int -build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg) +static void +build_ctf_archive_member (ctf_dict_t *ctf, const char *name, + struct ctf_per_tu_data *tup) { - struct ctf_per_tu_data *tup = (struct ctf_per_tu_data *) arg; ctf_dict_t *parent = tup->dict; if (strcmp (name, ".ctf") != 0) @@ -1433,8 +1456,6 @@ build_ctf_archive_member (ctf_dict_t *ctf, const char *name, void *arg) psymtab_storage *pss = tup->psf->get_partial_symtabs ().get (); scan_partial_symbols (ctf, pss, tup, name); - - return 0; } /* Read CTF debugging information from a BFD section. This is @@ -1446,6 +1467,9 @@ elfctf_build_psymtabs (struct objfile *of) { struct ctf_per_tu_data pcu; bfd *abfd = of->obfd.get (); + ctf_next_t *it = NULL; + ctf_dict_t *ctf; + const char *name; ctf_error_t err; ctf_archive_t *arc = ctf_bfdopen (abfd, &err); @@ -1467,8 +1491,13 @@ elfctf_build_psymtabs (struct objfile *of) of->qf.emplace_front (psf); pcu.psf = psf; - if (ctf_archive_iter (arc, build_ctf_archive_member, &pcu) < 0) - error (_("ctf_archive_iter failed in input file %s: - %s"), + while ((ctf = ctf_archive_next (arc, &it, &name, 0, &err)) != NULL) + { + build_ctf_archive_member (ctf, name, &pcu); + ctf_dict_close (ctf); + } + if (err != ECTF_NEXT_END) + error (_("ctf_archive_next failed in input file %s: - %s"), bfd_get_filename (abfd), ctf_errmsg (err)); } diff --git a/include/ctf-api.h b/include/ctf-api.h index 5d614439809..afa4e8289db 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -347,18 +347,6 @@ _CTF_ERRORS typedef int ctf_visit_f (ctf_dict_t *, const char *name, ctf_id_t type, size_t offset, int bit_width, int depth, void *arg); -typedef int ctf_member_f (ctf_dict_t *, const char *name, ctf_id_t membtype, - size_t offset, int bit_width, void *arg); -typedef int ctf_enum_f (const char *name, int64_t val, void *arg); -typedef int ctf_unsigned_enum_f (const char *name, uint64_t val, void *arg); -typedef int ctf_variable_f (ctf_dict_t *, const char *name, ctf_id_t type, - void *arg); -typedef int ctf_datasec_var_f (ctf_dict_t *fp, ctf_id_t type, size_t offset, - size_t datasec_size, void *arg); -typedef int ctf_type_f (ctf_dict_t *, ctf_id_t type, void *arg); -typedef int ctf_type_all_f (ctf_dict_t *, ctf_id_t type, int flag, void *arg); -typedef int ctf_type_kind_f (ctf_dict_t *, ctf_id_t type, int kind, void *arg); -typedef int ctf_archive_member_f (ctf_dict_t *fp, const char *name, void *arg); typedef int ctf_archive_raw_member_f (const char *name, const void *content, size_t len, void *arg); typedef char *ctf_dump_decorate_f (ctf_sect_names_t sect, @@ -845,14 +833,12 @@ extern ctf_id_t ctf_decl_tag (ctf_dict_t *, ctf_id_t decl_tag, the members of unnamed structs nested within this struct as if they were direct members, if CTF_MN_RECURSE is passed in the flags. */ -extern int ctf_member_iter (ctf_dict_t *, ctf_id_t, ctf_member_f *, void *); extern ssize_t ctf_member_next (ctf_dict_t *, ctf_id_t, ctf_next_t **, const char **name, ctf_id_t *membtype, int *bit_width, int flags); -/* Return all enumeration constants in a given enum type. The return value, and - VAL argument, may need to be cast to uint64_t: see ctf_enum_unsigned(). */ -extern int64_t ctf_enum_iter (ctf_dict_t *, ctf_id_t, ctf_enum_f *, void *); +/* Return all enumeration constants in a given enum type. The VAL argument may + need to be cast to uint64_t: see ctf_enum_unsigned(). */ extern const char *ctf_enum_next (ctf_dict_t *, ctf_id_t, ctf_next_t **, int64_t *); @@ -883,50 +869,40 @@ extern ctf_id_t ctf_arc_lookup_enumerator_next (ctf_archive_t *, const char *nam ctf_next_t **, int64_t *enum_value, ctf_dict_t **dict, ctf_error_t *errp); -/* Iterate over all types in a dict. ctf_type_iter_all recurses over all types: - ctf_type_iter recurses only over types with user-visible names (for which - CTF_ADD_ROOT was passed). All such types are returned, even if they are - things like pointers that intrinsically have no name: this is the only effect - of CTF_ADD_ROOT for such types. ctf_type_next allows you to choose whether - to see non-root types or not with the want_hidden arg: if set, the flag (if - passed) returns the non-root state of each type in turn. Types in parent - dictionaries are not returned. +/* Iterate over all types, kinds, variables, or datasecs in a dict. + ctf_type_next returns all types in a dict in turn, allowing you to choose + whether to see conflicting types or not with the want_hidden arg: if set, the + flag (if passed) returns the conflicting state of each type in turn. Types + in parent dictionaries are not returned. Note that this is the opposite of + the convention in the old API: a true value for the flag argument used to + mean it is visible; now it means it is conflicting. These days, even variables are included in the things returned by ctf_type*() (type kind CTF_K_VAR). */ -extern int ctf_type_iter (ctf_dict_t *, ctf_type_f *, void *); -extern int ctf_type_iter_all (ctf_dict_t *, ctf_type_all_f *, void *); -extern int ctf_type_kind_iter (ctf_dict_t *, int kind, ctf_type_kind_f *, void *); extern ctf_id_t ctf_type_next (ctf_dict_t *, ctf_next_t **, int *flag, int want_hidden); extern ctf_id_t ctf_type_kind_next (ctf_dict_t *, ctf_next_t **, int kind); - -extern int ctf_variable_iter (ctf_dict_t *, ctf_variable_f *, void *); extern ctf_id_t ctf_variable_next (ctf_dict_t *, ctf_next_t **, const char **); - -extern int ctf_datasec_var_iter (ctf_dict_t *, ctf_id_t, ctf_datasec_var_f *, - void *); extern ctf_id_t ctf_datasec_var_next (ctf_dict_t *, ctf_id_t, ctf_next_t **, size_t *size, size_t *offset); /* Iterate over all tags with the given TAG, returning the ID of each tag. */ extern ctf_id_t ctf_tag_next (ctf_dict_t *, const char *tag, ctf_next_t **); -/* ctf_archive_iter and ctf_archive_next open each member dict for you, - automatically importing any parent dict as usual: ctf_archive_iter closes the - dict on return from ctf_archive_member_f, but for ctf_archive_next the caller - must close each dict returned. If skip_parent is set, the parent dict is - skipped on the basis that it's already been seen in every child dict (but if - no child dicts exist, this will lead to nothing being returned). +/* ctf_archive_next opens each member dict for you, automatically importing any + parent dict as usual: the caller must close each dict returned once done with + it, though it may outlive the loop until the archive is closed; the cost of + opening is amortized so that repeated calls cost almost nothing. If + skip_parent is set, the parent dict is skipped on the basis that it's already + been seen in every child dict (but if no child dicts exist, this will lead to + nothing being returned). - If an open fails, ctf_archive_iter returns -1 early (losing the error), but - ctf_archive_next both passes back the error in the passed errp and allows you - to iterate past errors (until the usual ECTF_NEXT_END is returned). */ + If an open fails, ctf_archive_next both passes back the error in the passed + errp and allows you to iterate past errors (until the usual ECTF_NEXT_END is + returned). */ -extern int ctf_archive_iter (const ctf_archive_t *, ctf_archive_member_f *, - void *); extern ctf_dict_t *ctf_archive_next (const ctf_archive_t *, ctf_next_t **, const char **, int skip_parent, ctf_error_t *errp); diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c index d6b511f13fb..1650f591727 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -1828,37 +1828,6 @@ ctf_archive_raw_iter (const struct ctf_archive_internal *arci, return 0; } -/* Iterate over all CTF files in an archive: public entry point. We pass all - CTF files in turn to the specified callback function. */ -int -ctf_archive_iter (const struct ctf_archive_internal *arci, - ctf_archive_member_f *func, void *data) -{ - ctf_next_t *i = NULL; - ctf_dict_t *fp; - const char *name; - ctf_error_t err = 0; - - while ((fp = ctf_archive_next (arci, &i, &name, 0, &err)) != NULL) - { - int rc; - - if ((rc = func (fp, name, data)) != 0) - { - ctf_dict_close (fp); - ctf_next_destroy (i); - return rc; - } - ctf_dict_close (fp); - } - if (err != ECTF_NEXT_END && err != 0) - { - ctf_next_destroy (i); - return -1; - } - return 0; -} - /* Iterate over all CTF files in an archive, returning each dict in turn as a ctf_dict_t, and NULL on error or end of iteration. It is the caller's responsibility to close it. Parent dicts may be skipped. diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index d7f53cb5578..3437c856e9f 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -2226,42 +2226,44 @@ typedef struct ctf_bundle } ctf_bundle_t; static int -enumcmp (const char *name, int64_t value, void *arg) +enumcmp (ctf_dict_t *fp, ctf_id_t type, ctf_bundle_t *ctb, ctf_dict_t *err_fp) { - ctf_bundle_t *ctb = arg; + ctf_next_t *i = NULL; + const char *name; + int64_t value; int64_t bvalue; - if (ctf_enum_value (ctb->ctb_dict, ctb->ctb_type, name, &bvalue) < 0) + while ((name = ctf_enum_next (fp, type, &i, &value)) != NULL) { - ctf_err_warn (ctb->ctb_dict, 0, 0, - _("conflict due to enum %s iteration error"), name); - return 1; + if (ctf_enum_value (ctb->ctb_dict, ctb->ctb_type, name, &bvalue) < 0) + { + ctf_next_destroy (i); + ctf_err_warn (err_fp, 0, ctf_errno (ctb->ctb_dict), + _("conflict due to enum %s iteration error"), name); + return 1; + } + if (value != bvalue) + { + ctf_next_destroy (i); + ctf_err_warn (err_fp, 1, ECTF_CONFLICT, + _("conflict due to enum value change: %li versus %li"), + value, bvalue); + return 1; + } } - if (value != bvalue) + if (ctf_errno (fp) != ECTF_NEXT_END) { - ctf_err_warn (ctb->ctb_dict, 1, ECTF_CONFLICT, - _("conflict due to enum value change: %li versus %li"), - value, bvalue); + ctf_err_warn (err_fp, 0, ctf_errno (fp), + _("conflict due to enum %s iteration error"), name); return 1; } - return 0; -} - -static int -enumadd (const char *name, int64_t value, void *arg) -{ - ctf_bundle_t *ctb = arg; - return (ctf_add_enumerator (ctb->ctb_dict, ctb->ctb_type, - name, value) < 0); + return 0; } -static int -membcmp (ctf_dict_t *src_fp _libctf_unused_, const char *name, - ctf_id_t type _libctf_unused_, size_t offset, int bit_width, - void *arg) +static ctf_ret_t +membcmp (const char *name, size_t offset, int bit_width, ctf_bundle_t *ctb) { - ctf_bundle_t *ctb = arg; ctf_membinfo_t ctm; /* Don't check nameless members (e.g. anonymous structs/unions) against each @@ -2274,7 +2276,7 @@ membcmp (ctf_dict_t *src_fp _libctf_unused_, const char *name, ctf_err_warn (ctb->ctb_dict, 0, 0, _("conflict due to struct member %s iteration error"), name); - return 1; + return -1; } if (ctm.ctm_offset != offset) { @@ -2282,7 +2284,7 @@ membcmp (ctf_dict_t *src_fp _libctf_unused_, const char *name, _("conflict due to struct member %s offset change: " "%zx versus %zx"), name, ctm.ctm_offset, offset); - return 1; + return -1; } if (ctm.ctm_bit_width != bit_width) { @@ -2290,7 +2292,7 @@ membcmp (ctf_dict_t *src_fp _libctf_unused_, const char *name, _("conflict due to struct member %s bit-width change: " "%i versus %i"), name, ctm.ctm_bit_width, bit_width); - return 1; + return -1; } return 0; } @@ -2755,13 +2757,20 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT)); } - if (ctf_member_iter (src_fp, src_type, membcmp, &dst)) + while ((offset = ctf_member_next (src_fp, src_type, &i, + &membname, NULL, &bit_width, 0)) >= 0) { - ctf_err_warn (dst_fp, 1, ECTF_CONFLICT, - _("conflict for type %s against ID %lx: members " - "differ, see above"), name, dst_type); - return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT)); + if (membcmp (membname, offset, bit_width, &dst) < 0) + { + ctf_next_destroy (i); + ctf_err_warn (dst_fp, 1, ECTF_CONFLICT, + _("conflict for type %s against ID %lx: members " + "differ, see above"), name, dst_type); + return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT)); + } } + if (ctf_errno (src_fp) != ECTF_NEXT_END) + return CTF_ERR; /* errno is set for us. */ break; } @@ -2791,7 +2800,7 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type { if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE) { - ctf_next_destroy (i); + ctf_next_destroy (i); /* errno is set for us. */ break; } } @@ -2800,7 +2809,7 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type if (ctf_add_member_bitfield (dst_fp, dst_type, membname, dst_membtype, offset, bit_width) < 0) { - ctf_next_destroy (i); + ctf_next_destroy (i); /* errno is set for us. */ break; } } @@ -2822,8 +2831,8 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type "signedness differs"), name, dst_type); return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT)); } - if (ctf_enum_iter (src_fp, src_type, enumcmp, &dst) - || ctf_enum_iter (dst_fp, dst_type, enumcmp, &src)) + if (enumcmp (src_fp, src_type, &dst, dst_fp) + || enumcmp (dst_fp, dst_type, &src, dst_fp)) { ctf_err_warn (dst_fp, 1, ECTF_CONFLICT, _("conflict for enum %s against ID %lx: members " @@ -2834,17 +2843,37 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type else { ctf_snapshot_id_t snap = ctf_snapshot (dst_fp); + ctf_next_t *it = NULL; + const char *enum_name; + int64_t value; if (src_type == CTF_K_ENUM) dst_type = ctf_add_enum (dst_fp, flag, name); else dst_type = ctf_add_enum64 (dst_fp, flag, name); - if ((dst.ctb_type = dst_type) == CTF_ERR - || ctf_enum_iter (src_fp, src_type, enumadd, &dst)) + if (dst_type == CTF_ERR) + goto enum_err; + + while ((enum_name = ctf_enum_next (src_fp, src_type, + &it, &value)) != NULL) { - ctf_rollback (dst_fp, snap); - return CTF_ERR; /* errno is set for us */ + if (ctf_add_enumerator (dst_fp, dst_type, enum_name, value) < 0) + goto enum_err; } + if (ctf_errno (src_fp) != ECTF_NEXT_END) + { + ctf_set_errno (dst_fp, ctf_errno (src_fp)); + goto enum_err; + } + + break; + + enum_err: + { + ctf_next_destroy (it); + ctf_rollback (dst_fp, snap); + return CTF_ERR; /* errno is set for us. */ + } } break; diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c index 284ec07be4e..328e5fecf62 100644 --- a/libctf/ctf-dump.c +++ b/libctf/ctf-dump.c @@ -692,6 +692,11 @@ ctf_dump_datasecs (ctf_dict_t *fp, ctf_dump_state_t *arg) while ((type = ctf_type_kind_next (fp, &next, CTF_K_DATASEC)) != CTF_ERR) { + ctf_next_t *next_var = NULL; + ctf_id_t var_type; + size_t size; + size_t offset; + /* Dump DATASEC name. */ if (asprintf (&str, "%sSection %s:\n\n", first ? "" : "\n", @@ -702,12 +707,28 @@ ctf_dump_datasecs (ctf_dict_t *fp, ctf_dump_state_t *arg) first = 0; /* Dump all variables in the datasec. */ - if (ctf_datasec_var_iter (fp, type, ctf_dump_var, state) < 0) - goto err; + + while ((var_type = ctf_datasec_var_next (fp, type, &next_var, &size, + &offset)) != CTF_ERR) + { + if (ctf_dump_var (fp, type, offset, size, state) < 0) + { + ctf_err_warn (fp, 1, 0, _("cannot dump var %s (%lx) in datasec %s (%lx)\n"), + ctf_type_name_raw (fp, var_type), var_type, + ctf_type_name_raw (fp, type), type); + goto err; + } + } + if (ctf_errno (fp) != ECTF_NEXT_END) + { + ctf_err_warn (fp, 1, 0, _("cannot iterate over vars in datasec %s (%lx)\n"), + ctf_type_name_raw (fp, type), type); + goto err; + } } if (ctf_errno (fp) != ECTF_NEXT_END) { - ctf_err_warn (fp, 1, ctf_errno (fp), _("cannot visit datasecs\n")); + ctf_err_warn (fp, 1, ctf_errno (fp), _("cannot iterate over datasecs\n")); goto err; } @@ -789,13 +810,17 @@ type_hex_digits (ctf_id_t id) /* Dump a single type into the cds_items. */ static int -ctf_dump_type (ctf_dict_t *fp, ctf_id_t id, int flag, void *arg) +ctf_dump_type (ctf_dict_t *fp, ctf_id_t id, int hidden, + ctf_dump_state_t *state) { char *str; char *indent; - ctf_dump_state_t *state = arg; + int flag = CTF_ADD_ROOT; ctf_dump_membstate_t membstate = { &str, NULL }; + if (hidden) + flag = CTF_ADD_NONROOT; + /* Indent neatly. */ if (asprintf (&indent, " %*s", type_hex_digits (id), "") < 0) return (ctf_set_errno (fp, ENOMEM)); @@ -976,9 +1001,20 @@ ctf_dump (ctf_dict_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect, goto err; /* errno is set for us. */ break; case CTF_SECT_TYPE: - if (ctf_type_iter_all (fp, ctf_dump_type, state) < 0) - goto err; /* errno is set for us. */ - break; + { + ctf_next_t *it = NULL; + ctf_id_t type; + int hidden; + + while ((type = ctf_type_next (fp, &it, &hidden, 1)) != CTF_ERR) + { + if (ctf_dump_type (fp, type, hidden, state) < 0) + goto err; /* errno is set for us. */ + } + if (ctf_errno (fp) != ECTF_NEXT_END) + goto err; /* errno is set for us. */ + break; + } case CTF_SECT_STR: ctf_dump_str (fp, state); break; diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index cb7a82fe4a0..221b6d67853 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -162,34 +162,6 @@ ctf_vlen (ctf_dict_t *fp, ctf_id_t type, const ctf_type_t *tp, size_t *vlen_len) } } -/* 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. */ - -int -ctf_member_iter (ctf_dict_t *fp, ctf_id_t type, ctf_member_f *func, void *arg) -{ - ctf_next_t *i = NULL; - ssize_t offset; - int bit_width; - const char *name; - ctf_id_t membtype; - - while ((offset = ctf_member_next (fp, type, &i, &name, &membtype, - &bit_width, 0)) >= 0) - { - int rc; - if ((rc = func (fp, name, membtype, offset, bit_width, arg)) != 0) - { - ctf_next_destroy (i); - return rc; - } - } - if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ - - return 0; -} - /* Iterate over the members of a STRUCT or UNION, returning each member's offset and optionally name and member type in turn. On end-of-iteration, returns -1. If FLAGS is CTF_MN_RECURSE, recurse into unnamed members. */ @@ -371,31 +343,6 @@ ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, return ctf_set_errno (ofp, ECTF_NEXT_END); } -/* Iterate over the members of an ENUM. We pass the string name and associated - integer value of each enum element to the specified callback function. */ - -int64_t -ctf_enum_iter (ctf_dict_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg) -{ - ctf_next_t *i = NULL; - const char *name; - int64_t val; - - while ((name = ctf_enum_next (fp, type, &i, &val)) != NULL) - { - int rc; - if ((rc = func (name, val, arg)) != 0) - { - ctf_next_destroy (i); - return rc; - } - } - if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ - - return 0; -} - /* Iterate over the members of an enum TYPE, returning each enumerand's NAME or NULL at end of iteration or error, and optionally passing back the enumerand's integer VALue. */ @@ -500,98 +447,6 @@ ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it, return NULL; } -/* Iterate over every root (user-visible) type in the given CTF dict. We pass - the type ID of each type to the specified callback function. - - Does not traverse parent types: you have to do that explicitly. This is by - design, to avoid traversing them more than once if traversing many children - of a single parent. */ - -int -ctf_type_iter (ctf_dict_t *fp, ctf_type_f *func, void *arg) -{ - ctf_next_t *i = NULL; - ctf_id_t type; - - while ((type = ctf_type_next (fp, &i, NULL, 0)) != CTF_ERR) - { - int rc; - if ((rc = func (fp, type, arg)) != 0) - { - ctf_next_destroy (i); - return rc; - } - } - if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ - - return 0; -} - -/* Iterate over every type in the given CTF dict, user-visible or not. We pass - the type ID of each type to the specified callback function. - - Does not traverse parent types: you have to do that explicitly. This is by - design, to avoid traversing them more than once if traversing many children - of a single parent. */ - -int -ctf_type_iter_all (ctf_dict_t *fp, ctf_type_all_f *func, void *arg) -{ - ctf_next_t *i = NULL; - ctf_id_t type; - int flag; - - while ((type = ctf_type_next (fp, &i, &flag, 1)) != CTF_ERR) - { - int rc; - if ((rc = func (fp, type, flag, arg)) != 0) - { - ctf_next_destroy (i); - return rc; - } - } - if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ - - return 0; -} - -/* Iterate over every type of the given kind in the given CTF dict. - We pass the type ID of each type to the specified callback function. - - Types returned may be prefixed (but this is normally invisible): you can also - specifically traverse prefixed types by asking for CTF_K_BIG or CTF_K_HIDDEN. - In this case, the kind of the type returned will be different (the kind - prefixed). Using CTF_K_BIG may have unexpected results if types have been - added to this dict since it was opened, since types are only 'unbiggened' - upon being written out. - - Does not traverse parent types: you have to do that explicitly. This is by - design, to avoid traversing them more than once if traversing many children - of a single parent. */ - -int -ctf_type_kind_iter (ctf_dict_t *fp, int kind, ctf_type_kind_f *func, void *arg) -{ - ctf_next_t *i = NULL; - ctf_id_t type; - - while ((type = ctf_type_kind_next (fp, &i, kind)) != CTF_ERR) - { - int rc; - if ((rc = func (fp, type, kind, arg)) != 0) - { - ctf_next_destroy (i); - return rc; - } - } - if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ - - return 0; -} - /* Iterate over every type in the given CTF dict, optionally including non-user-visible types, returning each type ID and hidden flag in turn. Returns CTF_ERR on end of iteration or error. @@ -700,31 +555,6 @@ ctf_type_kind_next (ctf_dict_t *fp, ctf_next_t **it, int kind) return ctf_set_typed_errno (fp, ECTF_NEXT_END); } -/* Iterate over every variable in the given CTF dict, in arbitrary order. - We pass the name of each variable to the specified callback function. */ - -int -ctf_variable_iter (ctf_dict_t *fp, ctf_variable_f *func, void *arg) -{ - ctf_next_t *i = NULL; - ctf_id_t type; - const char *name; - - while ((type = ctf_variable_next (fp, &i, &name)) != CTF_ERR) - { - int rc; - if ((rc = func (fp, name, type, arg)) != 0) - { - ctf_next_destroy (i); - return rc; - } - } - if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ - - return 0; -} - /* Iterate over every variable in the given CTF dict, in arbitrary order, returning the name and type of each variable in turn. The name argument is not optional. Returns CTF_ERR on end of iteration or error. */ @@ -779,33 +609,6 @@ end: return ctf_set_typed_errno (fp, err); } -/* Iterate over every variable in the given DATASEC, in arbitrary order. We - pass the type ID, datasec-recorded size (usually 0), and offset of each - variable to the specified callback function. */ - -int -ctf_datasec_var_iter (ctf_dict_t *fp, ctf_id_t datasec, - ctf_datasec_var_f *func, void *arg) -{ - ctf_next_t *i = NULL; - ctf_id_t type; - size_t size, offset; - - while ((type = ctf_datasec_var_next (fp, datasec, &i, &size, &offset)) != CTF_ERR) - { - int rc; - if ((rc = func (fp, type, offset, size, arg)) != 0) - { - ctf_next_destroy (i); - return rc; - } - } - if (ctf_errno (fp) != ECTF_NEXT_END) - return -1; /* errno is set for us. */ - - return 0; -} - /* Iterate over every variable in the given CTF datasec, in arbitrary order, returning the name and type of each variable in turn. Returns CTF_ERR on end of iteration or error. diff --git a/libctf/libctf.ver b/libctf/libctf.ver index 1d0ddc403b1..35d9b1df5a7 100644 --- a/libctf/libctf.ver +++ b/libctf/libctf.ver @@ -103,17 +103,10 @@ LIBCTF_2.0 { ctf_lookup_enumerator_next; ctf_arc_lookup_enumerator_next; - ctf_member_iter; - ctf_enum_iter; ctf_enum_next; - ctf_type_iter; ctf_type_next; - ctf_type_iter_all; - ctf_type_kind_iter; ctf_type_kind_next; - ctf_variable_iter; ctf_variable_next; - ctf_datasec_iter; ctf_datasec_next; ctf_tag_next; @@ -182,7 +175,6 @@ LIBCTF_2.0 { ctf_arc_open_by_name; ctf_arc_open_by_name_sections; ctf_archive_count; - ctf_archive_iter; ctf_archive_next; ctf_archive_raw_iter; ctf_get_arc; diff --git a/libctf/testsuite/libctf-lookup/enum.c b/libctf/testsuite/libctf-lookup/enum.c index 1804b23a69e..8b498696584 100644 --- a/libctf/testsuite/libctf-lookup/enum.c +++ b/libctf/testsuite/libctf-lookup/enum.c @@ -2,13 +2,6 @@ #include #include -static int -print_enum (const char *name, int val, void *unused) -{ - printf ("iter test: %s has value %i\n", name, val); - return 0; -} - int main (int argc, char *argv[]) { @@ -48,9 +41,6 @@ main (int argc, char *argv[]) if ((type = ctf_lookup_by_name (fp, "enum ie") ) == CTF_ERR) goto err; - if ((ctf_enum_iter (fp, type, print_enum, NULL)) < 0) - goto ierr; - while ((name = ctf_enum_next (fp, type, &i, &val)) != NULL) { printf ("next test: %s has value %i\n", name, val); @@ -69,10 +59,7 @@ main (int argc, char *argv[]) err: fprintf (stderr, "Lookup failed: %s\n", ctf_errmsg (ctf_errno (fp))); return 1; - ierr: - fprintf (stderr, "_iter iteration failed: %s\n", ctf_errmsg (ctf_errno (fp))); - return 1; nerr: - fprintf (stderr, "_next iteration failed: %s\n", ctf_errmsg (ctf_errno (fp))); + fprintf (stderr, "iteration failed: %s\n", ctf_errmsg (ctf_errno (fp))); return 1; }