public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb/binutils-2_43-branch] libctf: clean up hashtab error handling mess
@ 2024-08-01 14:43 Nick Alcock
  0 siblings, 0 replies; only message in thread
From: Nick Alcock @ 2024-08-01 14:43 UTC (permalink / raw)
  To: binutils-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e24eb6404a606f6f78e35a3f6f11b57fd2364828

commit e24eb6404a606f6f78e35a3f6f11b57fd2364828
Author: Nick Alcock <nick.alcock@oracle.com>
Date:   Fri Jul 26 21:58:03 2024 +0100

    libctf: clean up hashtab error handling mess
    
    The dict and archive opening code in libctf is somewhat unusual, because
    unlike everything else, it cannot report errors by setting an error on the
    dict, because in case of error there isn't one.  They get passed an error
    integer pointer that is set on error instead.
    
    Inside ctf_bufopen this is implemented by calling ctf_set_open_errno and
    passing it a positive error value.  In turn this means that most things it
    calls (including init_static_types) return zero on success and a *positive*
    ECTF_* or errno value on error.
    
    This trickles down to ctf_dynhash_insert_type, which is used by
    init_static_types to add newly-detected types to the name tables.  This was
    returning the error value it received from a variety of functions without
    alteration.  ctf_dynhash_insert conformed to this contract by returning a
    positive value on error (usually OOM), which is unfortunate for multiple
    reasons:
    
    - ctf_dynset_insert returns a *negative* value
    - ctf_dynhash_insert and ctf_dynset_insert don't take an fp, so the value
      they return is turned into the errno, so it had better be right, callers
      don't just check for != 0 here
    - more or less every single caller of ctf_dyn*_insert in libctf other than
      ctf_dynhash_insert_type (and there are a *lot*, mostly in the
      deduplicator) assumes that ctf_dynhash_insert returns a negative value
      on error, even though it doesn't.  In practice the only possible error is
      OOM, but if OOM does happen we end up with a nonsense error value.
    
    The simplest fix for this seems to be to make ctf_dynhash_insert and
    ctf_dynset_insert conform to the usual interface contract: negative
    values are errors.  This in turn means that ctf_dynhash_insert_type
    needs to change: let's make it consistent too, returning a negative
    value on error, putting the error on the fp in non-negated form.
    
    init_static_types_internal adapts to this by negating the error return from
    ctf_dynhash_insert_type, so the value handed back to ctf_bufopen is still
    positive: the new call site in ctf_track_enumerator does not need to change.
    
    (The existing tests for this reliably detect when I get it wrong.
    I know, because they did.)
    
    libctf/
            * ctf-hash.c (ctf_dynhash_insert): Negate return value.
            (ctf_dynhash_insert_type): Set de-negated error on the dict:
            return negated error.
            * ctf-open.c (init_static_types_internal): Adapt to this change.

Diff:
---
 libctf/ctf-hash.c |  7 +++++--
 libctf/ctf-open.c | 20 +++++++++++---------
 2 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/libctf/ctf-hash.c b/libctf/ctf-hash.c
index 7f291e3ac27..cd7473419cb 100644
--- a/libctf/ctf-hash.c
+++ b/libctf/ctf-hash.c
@@ -256,7 +256,7 @@ ctf_dynhash_insert (ctf_dynhash_t *hp, void *key, void *value)
 			     key_free, value_free);
 
   if (!slot)
-    return errno;
+    return -errno;
 
   /* Keep track of the owner, so that the del function can get at the key_free
      and value_free functions.  Only do this if one of those functions is set:
@@ -786,7 +786,7 @@ ctf_dynhash_insert_type (ctf_dict_t *fp, ctf_dynhash_t *hp, uint32_t type,
     return EINVAL;
 
   if ((str = ctf_strptr_validate (fp, name)) == NULL)
-    return ctf_errno (fp);
+    return ctf_errno (fp) * -1;
 
   if (str[0] == '\0')
     return 0;		   /* Just ignore empty strings on behalf of caller.  */
@@ -795,6 +795,9 @@ ctf_dynhash_insert_type (ctf_dict_t *fp, ctf_dynhash_t *hp, uint32_t type,
 				 (void *) (ptrdiff_t) type)) == 0)
     return 0;
 
+  /* ctf_dynhash_insert returns a negative error value: negate it for
+     ctf_set_errno.  */
+  ctf_set_errno (fp, err * -1);
   return err;
 }
 
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index 3f624987f90..942a53a8f2c 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -681,6 +681,8 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
    the latest supported representation in the process, if needed, and if this
    recension of libctf supports upgrading.
 
+   Returns zero on success and a *positive* ECTF_* or errno value on error.
+
    This is a wrapper to simplify memory allocation on error in the _internal
    function that does all the actual work.  */
 
@@ -886,7 +888,7 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 					       LCTF_INDEX_TO_TYPE (fp, id, child),
 					       tp->ctt_name);
 		if (err != 0)
-		  return err;
+		  return err * -1;
 	      }
 	    break;
 	  }
@@ -905,7 +907,7 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 					 LCTF_INDEX_TO_TYPE (fp, id, child),
 					 tp->ctt_name);
 	  if (err != 0)
-	    return err;
+	    return err * -1;
 	  break;
 
 	case CTF_K_STRUCT:
@@ -920,7 +922,7 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 					 tp->ctt_name);
 
 	  if (err != 0)
-	    return err;
+	    return err * -1;
 
 	  break;
 
@@ -936,7 +938,7 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 					 tp->ctt_name);
 
 	  if (err != 0)
-	    return err;
+	    return err * -1;
 	  break;
 
 	case CTF_K_ENUM:
@@ -949,14 +951,14 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 					   tp->ctt_name);
 
 	    if (err != 0)
-	      return err;
+	      return err * -1;
 
 	    /* Remember all enums for later rescanning.  */
 
 	    err = ctf_dynset_insert (all_enums, (void *) (ptrdiff_t)
 				     LCTF_INDEX_TO_TYPE (fp, id, child));
 	    if (err != 0)
-	      return err;
+	      return err * -1;
 	    break;
 	  }
 
@@ -968,7 +970,7 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 					 LCTF_INDEX_TO_TYPE (fp, id, child),
 					 tp->ctt_name);
 	  if (err != 0)
-	    return err;
+	    return err * -1;
 	  break;
 
 	case CTF_K_FORWARD:
@@ -985,7 +987,7 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 		err = ctf_dynhash_insert_type (fp, h, LCTF_INDEX_TO_TYPE (fp, id, child),
 					       tp->ctt_name);
 		if (err != 0)
-		  return err;
+		  return err * -1;
 	      }
 	    break;
 	  }
@@ -1010,7 +1012,7 @@ init_static_types_internal (ctf_dict_t *fp, ctf_header_t *cth,
 					 LCTF_INDEX_TO_TYPE (fp, id, child),
 					 tp->ctt_name);
 	  if (err != 0)
-	    return err;
+	    return err * -1;
 	  break;
 	default:
 	  ctf_err_warn (fp, 0, ECTF_CORRUPT,

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-08-01 14:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-01 14:43 [binutils-gdb/binutils-2_43-branch] libctf: clean up hashtab error handling mess Nick Alcock

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).