[02/10] libctf: reimplemement many _iter iterators in terms of _next

Message ID 20210227132954.7766-3-nick.alcock@oracle.com
State New
Headers show
Series
  • libctf: cleanups, speedups, and bugfixes (one needing review)
Related show

Commit Message

Andreas Krebbel via Binutils Feb. 27, 2021, 1:29 p.m.
Ever since the generator-style _next iterators were introduced, there
have been separate implementations of the functional-style _iter
iterators that do the same thing as _next.

This is annoying and adds more dependencies on the internal guts of the
file format.  Rip them all out and replace them with the corresponding
_next iterators.  Only ctf_archive_raw_iter and ctf_label_iter survive,
the former because there is no access to the raw binary data of archives
via any _next iterator, and the latter because ctf_label_next hasn't
been implemented (because labels are currently not used for anything).

Tested by reverting the change (already applied) that reimplemented
ctf_member_iter in terms of ctf_member_next, then verifying that the
_iter and _next iterators produced the same results for every iterable
entity within a large type archive.

libctf/ChangeLog
2021-02-18  Nick Alcock  <nick.alcock@oracle.com>

	* ctf-types.c (ctf_member_iter): Move 'rc' to an inner scope.
	(ctf_enum_iter): Reimplement in terms of ctf_enum_next.
	(ctf_type_iter): Reimplement in terms of ctf_type_next.
	(ctf_type_iter_all): Likewise.
	(ctf_variable_iter): Reimplement in terms of ctf_variable_next.
	* ctf-archive.c (ctf_archive_iter_internal): Remove.
	(ctf_archive_iter): Reimplement in terms of ctf_archive_next.
---
 libctf/ChangeLog     |  10 ++++
 libctf/ctf-archive.c |  68 ++++++-------------------
 libctf/ctf-types.c   | 115 +++++++++++++++++--------------------------
 3 files changed, 69 insertions(+), 124 deletions(-)

-- 
2.30.0.252.gc27e85e57d

Patch

diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index d8857301388..2d7b846fbb1 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,3 +1,13 @@ 
+2021-02-18  Nick Alcock  <nick.alcock@oracle.com>
+
+	* ctf-types.c (ctf_member_iter): Move 'rc' to an inner scope.
+	(ctf_enum_iter): Reimplement in terms of ctf_enum_next.
+	(ctf_type_iter): Reimplement in terms of ctf_type_next.
+	(ctf_type_iter_all): Likewise.
+	(ctf_variable_iter): Reimplement in terms of ctf_variable_next.
+	* ctf-archive.c (ctf_archive_iter_internal): Remove.
+	(ctf_archive_iter): Reimplement in terms of ctf_archive_next.
+
 2021-02-18  Nick Alcock  <nick.alcock@oracle.com>
 
 	* ctf-archive.c (ctf_archive_next): Set the name of parents in
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c
index 6e1bf151f1a..8b8e170241f 100644
--- a/libctf/ctf-archive.c
+++ b/libctf/ctf-archive.c
@@ -1043,70 +1043,32 @@  ctf_archive_raw_iter (const ctf_archive_t *arc,
   return -EINVAL;			 /* Not supported. */
 }
 
-/* Iterate over all CTF files in an archive.  We pass all CTF files in turn to
-   the specified callback function.  */
-static int
-ctf_archive_iter_internal (const ctf_archive_t *wrapper,
-			   const struct ctf_archive *arc,
-			   const ctf_sect_t *symsect,
-			   const ctf_sect_t *strsect,
-			   ctf_archive_member_f *func, void *data)
+/* 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 ctf_archive_t *arc, ctf_archive_member_f *func,
+		  void *data)
 {
-  int rc;
-  size_t i;
-  ctf_dict_t *f;
-  struct ctf_archive_modent *modent;
-  const char *nametbl;
-
-  modent = (ctf_archive_modent_t *) ((char *) arc
-				     + sizeof (struct ctf_archive));
-  nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
+  ctf_next_t *i = NULL;
+  ctf_dict_t *fp;
+  const char *name;
+  int err;
 
-  for (i = 0; i < le64toh (arc->ctfa_ndicts); i++)
+  while ((fp = ctf_archive_next (arc, &i, &name, 0, &err)) != NULL)
     {
-      const char *name;
+      int rc;
 
-      name = &nametbl[le64toh (modent[i].name_offset)];
-      if ((f = ctf_dict_open_internal (arc, symsect, strsect,
-				       name,
-				       wrapper->ctfi_symsect_little_endian,
-				       &rc)) == NULL)
-	return rc;
-
-      f->ctf_archive = (ctf_archive_t *) wrapper;
-      ctf_arc_import_parent (wrapper, f);
-      if ((rc = func (f, name, data)) != 0)
+      if ((rc = func (fp, name, data)) != 0)
 	{
-	  ctf_dict_close (f);
+	  ctf_dict_close (fp);
+	  ctf_next_destroy (i);
 	  return rc;
 	}
-
-      ctf_dict_close (f);
+      ctf_dict_close (fp);
     }
   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 ctf_archive_t *arc, ctf_archive_member_f *func,
-		  void *data)
-{
-  const ctf_sect_t *symsect = &arc->ctfi_symsect;
-  const ctf_sect_t *strsect = &arc->ctfi_strsect;
-
-  if (symsect->cts_name == NULL)
-    symsect = NULL;
-  if (strsect->cts_name == NULL)
-    strsect = NULL;
-
-  if (arc->ctfi_is_archive)
-    return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
-				      func, data);
-
-  return func (arc->ctfi_dict, _CTF_SECTION, data);
-}
-
 /* 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-types.c b/libctf/ctf-types.c
index 57a284d82e7..28c5c7aa1e1 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -45,10 +45,10 @@  ctf_member_iter (ctf_dict_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
   ssize_t offset;
   const char *name;
   ctf_id_t membtype;
-  int rc;
 
   while ((offset = ctf_member_next (fp, type, &i, &name, &membtype, 0)) >= 0)
     {
+      int rc;
       if ((rc = func (name, membtype, offset, arg)) != 0)
 	{
 	  ctf_next_destroy (i);
@@ -255,47 +255,21 @@  ctf_member_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
 int
 ctf_enum_iter (ctf_dict_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
 {
-  ctf_dict_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 -1;			/* errno is set for us.  */
-
-  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
-    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);
+  ctf_next_t *i = NULL;
+  const char *name;
+  int val;
 
-  if ((dtd = ctf_dynamic_type (ofp, type)) == NULL)
+  while ((name = ctf_enum_next (fp, type, &i, &val)) != NULL)
     {
-      ep = (const ctf_enum_t *) ((uintptr_t) tp + increment);
-
-      for (n = LCTF_INFO_VLEN (fp, tp->ctt_info); n != 0; n--, ep++)
+      int rc;
+      if ((rc = func (name, val, arg)) != 0)
 	{
-	  const char *name = ctf_strptr (fp, ep->cte_name);
-	  if ((rc = func (name, ep->cte_value, arg)) != 0)
-	    return rc;
-	}
-    }
-  else
-    {
-      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;
+	  ctf_next_destroy (i);
+	  return rc;
 	}
     }
+  if (ctf_errno (fp) != ECTF_NEXT_END)
+    return -1;					/* errno is set for us.  */
 
   return 0;
 }
@@ -424,16 +398,20 @@  ctf_enum_next (ctf_dict_t *fp, ctf_id_t type, ctf_next_t **it,
 int
 ctf_type_iter (ctf_dict_t *fp, ctf_type_f *func, void *arg)
 {
-  ctf_id_t id, max = fp->ctf_typemax;
-  int rc, child = (fp->ctf_flags & LCTF_CHILD);
+  ctf_next_t *i = NULL;
+  ctf_id_t type;
 
-  for (id = 1; id <= max; id++)
+  while ((type = ctf_type_next (fp, &i, NULL, 0)) != CTF_ERR)
     {
-      const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
-      if (LCTF_INFO_ISROOT (fp, tp->ctt_info)
-	  && (rc = func (LCTF_INDEX_TO_TYPE (fp, id, child), arg)) != 0)
-	return rc;
+      int rc;
+      if ((rc = func (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;
 }
@@ -448,17 +426,21 @@  ctf_type_iter (ctf_dict_t *fp, ctf_type_f *func, void *arg)
 int
 ctf_type_iter_all (ctf_dict_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);
+  ctf_next_t *i = NULL;
+  ctf_id_t type;
+  int flag;
 
-  for (id = 1; id <= max; id++)
+  while ((type = ctf_type_next (fp, &i, &flag, 1)) != CTF_ERR)
     {
-      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;
+      int rc;
+      if ((rc = func (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;
 }
@@ -518,30 +500,21 @@  ctf_type_next (ctf_dict_t *fp, ctf_next_t **it, int *flag, int want_hidden)
 int
 ctf_variable_iter (ctf_dict_t *fp, ctf_variable_f *func, void *arg)
 {
-  int rc;
-
-  if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
-    return (ctf_set_errno (fp, ECTF_NOPARENT));
+  ctf_next_t *i = NULL;
+  ctf_id_t type;
+  const char *name;
 
-  if (!(fp->ctf_flags & LCTF_RDWR))
+  while ((type = ctf_variable_next (fp, &i, &name)) != CTF_ERR)
     {
-      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))
+      int rc;
+      if ((rc = func (name, type, arg)) != 0)
 	{
-	  if ((rc = func (dvd->dvd_name, dvd->dvd_type, arg)) != 0)
-	    return rc;
+	  ctf_next_destroy (i);
+	  return rc;
 	}
     }
+  if (ctf_errno (fp) != ECTF_NEXT_END)
+    return -1;					/* errno is set for us.  */
 
   return 0;
 }