[v7] libctf: Sanitize error types for PR 30836

Message ID 20231009151146.3818141-1-torbjorn.svensson@foss.st.com
State New
Headers
Series [v7] libctf: Sanitize error types for PR 30836 |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Testing passed

Commit Message

Torbjorn SVENSSON Oct. 9, 2023, 3:11 p.m. UTC
  v1 -> v2:
Changed all functions with signed integer return type to return -1 based on
comment from Alan.

v2 -> v3:
Added ctf_set_errno_signed function to return a signed -1 value based on
comment from Nick.

v3 -> v4:
- Moved ctf_set_errno_signed function to ctf-inlines.h, renamed it to
ctf_set_int_errno and converted it to an inline function.
- Moved ctf_set_errno function to ctf-inlines.h, renamed it to
ctf_set_type_errno, changed return type to ctf_id_t and converted it to an
inline function.
- Updated the changelog entry in the commit message. Is this list really
required? I don't think it give much information in this patch and 'git log'
have mixed commits (some have the entry while others don't).

v4 -> v5:
Updated in accordance with comments from Nick.
- Changed return type to void for ctf_set_errno.
- Inline the return on every call to ctf_set_errno.
- Merged ctf_set_int_errno and ctf_set_type_errno into ctf_set_errno.
- Droped log entry as it's too many places with this change to make it
  readable.
- Corrected a few places where -1 was returned where it should have been
  CTF_ERR.

v4 -> v6:
Updated in accordance with comments from Nick.
Patch is now mostly v4 again with additions:
- Renamed ctf_set_type_errno to ctf_set_typed_errno.
- Renamed ctf_set_int_errno to ctf_set_errno.
- Droped log entry as it's too many places with this change to make it
  readable.
- Corrected a few places where -1 was returned where it should have been
  CTF_ERR.

v6 -> v7:
- Reverted chunks that called ctf_set_type_errno in v6 that does not return
  to reduce the number of changed. Thanks Yvan ROUX for pointing this out.



@Nick: Can you please try this is in your test bench and let me know if it's
ok for trunk?

--


Made sure there is no implicit conversion between signed and unsigned
return value for functions setting the ctf_errno value.
An example of the problem is that in ctf_member_next, the "offset" value
is either 0L or (ctf_id_t)-1L, but it should have been 0L or -1L.
The issue was discovered while building a 64 bit ld binary to be
executed on the Windows platform.
Example object file that demonstrates the issue is attached in the PR.

Signed-off-by: Torbjörn SVENSSON <torbjorn.svensson@foss.st.com>
Co-Authored-By: Yvan ROUX <yvan.roux@foss.st.com>
---
 libctf/ctf-create.c  | 95 ++++++++++++++++++++------------------------
 libctf/ctf-dedup.c   | 15 ++++---
 libctf/ctf-impl.h    |  1 -
 libctf/ctf-inlines.h | 17 ++++++++
 libctf/ctf-labels.c  |  4 +-
 libctf/ctf-link.c    | 15 +++----
 libctf/ctf-lookup.c  | 52 ++++++++++++------------
 libctf/ctf-types.c   | 43 ++++++++++----------
 libctf/ctf-util.c    | 10 -----
 9 files changed, 122 insertions(+), 130 deletions(-)
  

Comments

Nick Alcock Oct. 11, 2023, 11:14 a.m. UTC | #1
On 9 Oct 2023, Torbjörn SVENSSON uttered the following:

> @Nick: Can you please try this is in your test bench and let me know if it's
> ok for trunk?

I think I'll write a testcase too (it'll only show anything on mingw64,
but having testcases that verify that errors are actually seen as errors
seems wise in any case), but yes, testing is about to start :) looks
good at first sight, but I hvaen't tried it on the affected systems yet.
(Presumably a build actually *on* mingw would be affected too, which is
one of my routine test envs.)
  

Patch

diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index 6b342dc64a2..fff18e529be 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -225,10 +225,7 @@  ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
   const char *name;
   if (ctf_dynhash_insert (fp->ctf_dthash, (void *) (uintptr_t) dtd->dtd_type,
 			  dtd) < 0)
-    {
-      ctf_set_errno (fp, ENOMEM);
-      return -1;
-    }
+    return ctf_set_errno (fp, ENOMEM);
 
   if (flag == CTF_ADD_ROOT && dtd->dtd_data.ctt_name
       && (name = ctf_strraw (fp, dtd->dtd_data.ctt_name)) != NULL)
@@ -239,8 +236,7 @@  ctf_dtd_insert (ctf_dict_t *fp, ctf_dtdef_t *dtd, int flag, int kind)
 	{
 	  ctf_dynhash_remove (fp->ctf_dthash, (void *) (uintptr_t)
 			      dtd->dtd_type);
-	  ctf_set_errno (fp, ENOMEM);
-	  return -1;
+	  return ctf_set_errno (fp, ENOMEM);
 	}
     }
   ctf_list_append (&fp->ctf_dtdefs, dtd);
@@ -329,10 +325,7 @@  int
 ctf_dvd_insert (ctf_dict_t *fp, ctf_dvdef_t *dvd)
 {
   if (ctf_dynhash_insert (fp->ctf_dvhash, dvd->dvd_name, dvd) < 0)
-    {
-      ctf_set_errno (fp, ENOMEM);
-      return -1;
-    }
+    return ctf_set_errno (fp, ENOMEM);
   ctf_list_append (&fp->ctf_dvdefs, dvd);
   return 0;
 }
@@ -453,23 +446,23 @@  ctf_add_generic (ctf_dict_t *fp, uint32_t flag, const char *name, int kind,
   ctf_id_t type;
 
   if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   if (!(fp->ctf_flags & LCTF_RDWR))
-    return (ctf_set_errno (fp, ECTF_RDONLY));
+    return (ctf_set_typed_errno (fp, ECTF_RDONLY));
 
   if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) >= CTF_MAX_TYPE)
-    return (ctf_set_errno (fp, ECTF_FULL));
+    return (ctf_set_typed_errno (fp, ECTF_FULL));
 
   if (LCTF_INDEX_TO_TYPE (fp, fp->ctf_typemax, 1) == (CTF_MAX_PTYPE - 1))
-    return (ctf_set_errno (fp, ECTF_FULL));
+    return (ctf_set_typed_errno (fp, ECTF_FULL));
 
   /* Make sure ptrtab always grows to be big enough for all types.  */
   if (ctf_grow_ptrtab (fp) < 0)
       return CTF_ERR;				/* errno is set for us. */
 
   if ((dtd = calloc (1, sizeof (ctf_dtdef_t))) == NULL)
-    return (ctf_set_errno (fp, EAGAIN));
+    return (ctf_set_typed_errno (fp, EAGAIN));
 
   dtd->dtd_vlen_alloc = vlen;
   if (vlen > 0)
@@ -532,13 +525,13 @@  ctf_add_encoded (ctf_dict_t *fp, uint32_t flag,
   uint32_t encoding;
 
   if (ep == NULL)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   if (name == NULL || name[0] == '\0')
-    return (ctf_set_errno (fp, ECTF_NONAME));
+    return (ctf_set_typed_errno (fp, ECTF_NONAME));
 
   if (!ctf_assert (fp, kind == CTF_K_INTEGER || kind == CTF_K_FLOAT))
-    return -1;					/* errno is set for us.  */
+    return CTF_ERR;					/* errno is set for us.  */
 
   if ((type = ctf_add_generic (fp, flag, name, kind, sizeof (uint32_t),
 			       &dtd)) == CTF_ERR)
@@ -570,7 +563,7 @@  ctf_add_reftype (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref, uint32_t kind)
   int child = fp->ctf_flags & LCTF_CHILD;
 
   if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
     return CTF_ERR;		/* errno is set for us.  */
@@ -613,13 +606,13 @@  ctf_add_slice (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref,
   ctf_dict_t *tmp = fp;
 
   if (ep == NULL)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   if ((ep->cte_bits > 255) || (ep->cte_offset > 255))
-    return (ctf_set_errno (fp, ECTF_SLICEOVERFLOW));
+    return (ctf_set_typed_errno (fp, ECTF_SLICEOVERFLOW));
 
   if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   if (ref != 0 && ((tp = ctf_lookup_by_id (&tmp, ref)) == NULL))
     return CTF_ERR;		/* errno is set for us.  */
@@ -634,7 +627,7 @@  ctf_add_slice (ctf_dict_t *fp, uint32_t flag, ctf_id_t ref,
   if ((kind != CTF_K_INTEGER) && (kind != CTF_K_FLOAT) &&
       (kind != CTF_K_ENUM)
       && (ref != 0))
-    return (ctf_set_errno (fp, ECTF_NOTINTFP));
+    return (ctf_set_typed_errno (fp, ECTF_NOTINTFP));
 
   if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_SLICE,
 			       sizeof (ctf_slice_t), &dtd)) == CTF_ERR)
@@ -682,7 +675,7 @@  ctf_add_array (ctf_dict_t *fp, uint32_t flag, const ctf_arinfo_t *arp)
   ctf_dict_t *tmp = fp;
 
   if (arp == NULL)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   if (arp->ctr_contents != 0
       && ctf_lookup_by_id (&tmp, arp->ctr_contents) == NULL)
@@ -697,7 +690,7 @@  ctf_add_array (ctf_dict_t *fp, uint32_t flag, const ctf_arinfo_t *arp)
       ctf_err_warn (fp, 1, ECTF_INCOMPLETE,
 		    _("ctf_add_array: index type %lx is incomplete"),
 		    arp->ctr_contents);
-      return (ctf_set_errno (fp, ECTF_INCOMPLETE));
+      return (ctf_set_typed_errno (fp, ECTF_INCOMPLETE));
     }
 
   if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_ARRAY,
@@ -751,11 +744,11 @@  ctf_add_function (ctf_dict_t *fp, uint32_t flag,
   size_t i;
 
   if (!(fp->ctf_flags & LCTF_RDWR))
-    return (ctf_set_errno (fp, ECTF_RDONLY));
+    return (ctf_set_typed_errno (fp, ECTF_RDONLY));
 
   if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0
       || (ctc->ctc_argc != 0 && argv == NULL))
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   vlen = ctc->ctc_argc;
   if (ctc->ctc_flags & CTF_FUNC_VARARG)
@@ -766,7 +759,7 @@  ctf_add_function (ctf_dict_t *fp, uint32_t flag,
     return CTF_ERR;				/* errno is set for us.  */
 
   if (vlen > CTF_MAX_VLEN)
-    return (ctf_set_errno (fp, EOVERFLOW));
+    return (ctf_set_typed_errno (fp, EOVERFLOW));
 
   /* One word extra allocated for padding for 4-byte alignment if need be.
      Not reflected in vlen: we don't want to copy anything into it, and
@@ -818,7 +811,7 @@  ctf_add_struct_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
   if (dtd->dtd_vlen_alloc == 0)
     {
       if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
-	return (ctf_set_errno (fp, ENOMEM));
+	return (ctf_set_typed_errno (fp, ENOMEM));
       dtd->dtd_vlen_alloc = initial_vlen;
     }
 
@@ -858,7 +851,7 @@  ctf_add_union_sized (ctf_dict_t *fp, uint32_t flag, const char *name,
   if (dtd->dtd_vlen_alloc == 0)
     {
       if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
-	return (ctf_set_errno (fp, ENOMEM));
+	return (ctf_set_typed_errno (fp, ENOMEM));
       dtd->dtd_vlen_alloc = initial_vlen;
     }
 
@@ -897,7 +890,7 @@  ctf_add_enum (ctf_dict_t *fp, uint32_t flag, const char *name)
   if (dtd->dtd_vlen_alloc == 0)
     {
       if ((dtd->dtd_vlen = calloc (1, initial_vlen)) == NULL)
-	return (ctf_set_errno (fp, ENOMEM));
+	return (ctf_set_typed_errno (fp, ENOMEM));
       dtd->dtd_vlen_alloc = initial_vlen;
     }
 
@@ -925,7 +918,7 @@  ctf_add_enum_encoded (ctf_dict_t *fp, uint32_t flag, const char *name,
     {
       if ((ctf_type_kind (fp, type) != CTF_K_FORWARD) &&
 	  (ctf_type_kind_unsliced (fp, type) != CTF_K_ENUM))
-	return (ctf_set_errno (fp, ECTF_NOTINTFP));
+	return (ctf_set_typed_errno (fp, ECTF_NOTINTFP));
     }
   else if ((type = ctf_add_enum (fp, flag, name)) == CTF_ERR)
     return CTF_ERR;		/* errno is set for us.  */
@@ -943,10 +936,10 @@  ctf_add_forward (ctf_dict_t *fp, uint32_t flag, const char *name,
   ctf_id_t type = 0;
 
   if (!ctf_forwardable_kind (kind))
-    return (ctf_set_errno (fp, ECTF_NOTSUE));
+    return (ctf_set_typed_errno (fp, ECTF_NOTSUE));
 
   if (name == NULL || name[0] == '\0')
-    return (ctf_set_errno (fp, ECTF_NONAME));
+    return (ctf_set_typed_errno (fp, ECTF_NONAME));
 
   /* If the type is already defined or exists as a forward tag, just
      return the ctf_id_t of the existing definition.  */
@@ -985,7 +978,7 @@  ctf_add_unknown (ctf_dict_t *fp, uint32_t flag, const char *name)
 			_("ctf_add_unknown: cannot add unknown type "
 			  "named %s: type of this name already defined"),
 			name ? name : _("(unnamed type)"));
-	  return (ctf_set_errno (fp, ECTF_CONFLICT));
+	  return (ctf_set_typed_errno (fp, ECTF_CONFLICT));
 	}
     }
 
@@ -1007,10 +1000,10 @@  ctf_add_typedef (ctf_dict_t *fp, uint32_t flag, const char *name,
   ctf_dict_t *tmp = fp;
 
   if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   if (name == NULL || name[0] == '\0')
-    return (ctf_set_errno (fp, ECTF_NONAME));
+    return (ctf_set_typed_errno (fp, ECTF_NONAME));
 
   if (ref != 0 && ctf_lookup_by_id (&tmp, ref) == NULL)
     return CTF_ERR;		/* errno is set for us.  */
@@ -1575,14 +1568,14 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
   ctf_id_t orig_src_type = src_type;
 
   if (!(dst_fp->ctf_flags & LCTF_RDWR))
-    return (ctf_set_errno (dst_fp, ECTF_RDONLY));
+    return (ctf_set_typed_errno (dst_fp, ECTF_RDONLY));
 
   if ((src_tp = ctf_lookup_by_id (&src_fp, src_type)) == NULL)
-    return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
+    return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
 
   if ((ctf_type_resolve (src_fp, src_type) == CTF_ERR)
       && (ctf_errno (src_fp) == ECTF_NONREPRESENTABLE))
-    return (ctf_set_errno (dst_fp, ECTF_NONREPRESENTABLE));
+    return (ctf_set_typed_errno (dst_fp, ECTF_NONREPRESENTABLE));
 
   name = ctf_strptr (src_fp, src_tp->ctt_name);
   kind = LCTF_INFO_KIND (src_fp, src_tp->ctt_info);
@@ -1661,7 +1654,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 			_("ctf_add_type: conflict for type %s: "
 			  "kinds differ, new: %i; old (ID %lx): %i"),
 			name, kind, dst_type, dst_kind);
-	  return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+	  return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
 	}
     }
 
@@ -1672,7 +1665,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
   if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT || kind == CTF_K_SLICE)
     {
       if (ctf_type_encoding (src_fp, src_type, &src_en) != 0)
-	return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
+	return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
 
       if (dst_type != CTF_ERR)
 	{
@@ -1702,7 +1695,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 		}
 	      else
 		  {
-		    return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+		    return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
 		  }
 	    }
 	  else
@@ -1740,7 +1733,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 
   if (ctf_dynhash_insert (proc_tracking_fp->ctf_add_processing,
 			  (void *) (uintptr_t) src_type, (void *) 1) < 0)
-    return ctf_set_errno (dst_fp, ENOMEM);
+    return ctf_set_typed_errno (dst_fp, ENOMEM);
 
   switch (kind)
     {
@@ -1785,7 +1778,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 
     case CTF_K_ARRAY:
       if (ctf_array_info (src_fp, src_type, &src_ar) != 0)
-	return (ctf_set_errno (dst_fp, ctf_errno (src_fp)));
+	return (ctf_set_typed_errno (dst_fp, ctf_errno (src_fp)));
 
       src_ar.ctr_contents =
 	ctf_add_type_internal (dst_fp, src_fp, src_ar.ctr_contents,
@@ -1812,7 +1805,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 			    src_ar.ctr_index, src_ar.ctr_nelems,
 			    dst_ar.ctr_contents, dst_ar.ctr_index,
 			    dst_ar.ctr_nelems);
-	      return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+	      return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
 	    }
 	}
       else
@@ -1859,7 +1852,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 				"size differs, old %li, new %li"), name,
 			      dst_type, (long) ctf_type_size (src_fp, src_type),
 			      (long) ctf_type_size (dst_fp, dst_type));
-		return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+		return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
 	      }
 
 	    if (ctf_member_iter (src_fp, src_type, membcmp, &dst))
@@ -1867,7 +1860,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 		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_errno (dst_fp, ECTF_CONFLICT));
+		return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
 	      }
 
 	    break;
@@ -1925,7 +1918,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
 	      ctf_err_warn (dst_fp, 1, ECTF_CONFLICT,
 			    _("conflict for enum %s against ID %lx: members "
 			      "differ, see above"), name, dst_type);
-	      return (ctf_set_errno (dst_fp, ECTF_CONFLICT));
+	      return (ctf_set_typed_errno (dst_fp, ECTF_CONFLICT));
 	    }
 	}
       else
@@ -1964,7 +1957,7 @@  ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
       break;
 
     default:
-      return (ctf_set_errno (dst_fp, ECTF_CORRUPT));
+      return (ctf_set_typed_errno (dst_fp, ECTF_CORRUPT));
     }
 
   if (dst_type != CTF_ERR)
@@ -1985,7 +1978,7 @@  ctf_add_type (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type)
   /* We store the hash on the source, because it contains only source type IDs:
      but callers will invariably expect errors to appear on the dest.  */
   if (!src_fp->ctf_add_processing)
-    return (ctf_set_errno (dst_fp, ENOMEM));
+    return (ctf_set_typed_errno (dst_fp, ENOMEM));
 
   id = ctf_add_type_internal (dst_fp, src_fp, src_type, src_fp);
   ctf_dynhash_empty (src_fp->ctf_add_processing);
diff --git a/libctf/ctf-dedup.c b/libctf/ctf-dedup.c
index 5fdddfd0b54..7a4b8584a4e 100644
--- a/libctf/ctf-dedup.c
+++ b/libctf/ctf-dedup.c
@@ -1318,8 +1318,7 @@  ctf_dedup_mark_conflicting_hash (ctf_dict_t *fp, const char *hval)
   if (ctf_dynset_cinsert (d->cd_conflicting_types, hval) < 0)
     {
       ctf_dprintf ("Out of memory marking %s as conflicted\n", hval);
-      ctf_set_errno (fp, errno);
-      return -1;
+      return ctf_set_errno (fp, errno);
     }
 
   /* If any types cite this type, mark them conflicted too.  */
@@ -2525,7 +2524,7 @@  ctf_dedup_id_to_target (ctf_dict_t *output, ctf_dict_t *target,
   if ((input->ctf_flags & LCTF_CHILD) && (LCTF_TYPE_ISPARENT (input, id)))
     {
       if (!ctf_assert (output, parents[input_num] <= ninputs))
-	return -1;
+	return CTF_ERR;
       input = inputs[parents[input_num]];
       input_num = parents[input_num];
     }
@@ -2534,7 +2533,7 @@  ctf_dedup_id_to_target (ctf_dict_t *output, ctf_dict_t *target,
 			     CTF_DEDUP_GID (output, input_num, id));
 
   if (!ctf_assert (output, hval && td->cd_output_emission_hashes))
-    return -1;
+    return CTF_ERR;
 
   /* If this type is a conflicted tagged structure, union, or forward,
      substitute a synthetic forward instead, emitting it if need be.  Only do
@@ -2553,7 +2552,7 @@  ctf_dedup_id_to_target (ctf_dict_t *output, ctf_dict_t *target,
       ctf_set_errno (err_fp, ctf_errno (output));
       ctf_err_warn (err_fp, 0, 0, _("cannot add synthetic forward for type "
 				    "%i/%lx"), input_num, id);
-      return -1;
+      return CTF_ERR;
     default:
       return emitted_forward;
     }
@@ -2568,7 +2567,7 @@  ctf_dedup_id_to_target (ctf_dict_t *output, ctf_dict_t *target,
       ctf_dprintf ("Checking shared parent for target\n");
       if (!ctf_assert (output, (target != output)
 		       && (target->ctf_flags & LCTF_CHILD)))
-	return -1;
+	return CTF_ERR;
 
       target_id = ctf_dynhash_lookup (od->cd_output_emission_hashes, hval);
 
@@ -2582,13 +2581,13 @@  ctf_dedup_id_to_target (ctf_dict_t *output, ctf_dict_t *target,
 	  ctf_err_warn (err_fp, 0, ctf_errno (output),
 			_("cannot add synthetic forward for type %i/%lx"),
 			input_num, id);
-	  return ctf_set_errno (err_fp, ctf_errno (output));
+	  return ctf_set_typed_errno (err_fp, ctf_errno (output));
 	default:
 	  return emitted_forward;
 	}
     }
   if (!ctf_assert (output, target_id))
-    return -1;
+    return CTF_ERR;
   return (ctf_id_t) (uintptr_t) target_id;
 }
 
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index da687762c89..77d74ef0ea9 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -741,7 +741,6 @@  extern struct ctf_archive *ctf_arc_open_internal (const char *, int *);
 extern void ctf_arc_close_internal (struct ctf_archive *);
 extern const ctf_preamble_t *ctf_arc_bufpreamble (const ctf_sect_t *);
 extern void *ctf_set_open_errno (int *, int);
-extern unsigned long ctf_set_errno (ctf_dict_t *, int);
 extern void ctf_flip_header (ctf_header_t *);
 extern int ctf_flip (ctf_dict_t *, ctf_header_t *, unsigned char *, int);
 
diff --git a/libctf/ctf-inlines.h b/libctf/ctf-inlines.h
index 6bda68d68e6..84044a1d16c 100644
--- a/libctf/ctf-inlines.h
+++ b/libctf/ctf-inlines.h
@@ -90,6 +90,23 @@  ctf_assert_internal (ctf_dict_t *fp, const char *file, size_t line,
   return expr;
 }
 
+static inline int
+ctf_set_errno (ctf_dict_t *fp, int err)
+{
+  fp->ctf_errno = err;
+  /* Don't rely on CTF_ERR here as it will not properly sign extend on 64-bit
+     Windows ABI.  */
+  return -1;
+}
+
+static inline ctf_id_t
+ctf_set_typed_errno (ctf_dict_t *fp, int err)
+{
+  fp->ctf_errno = err;
+  return CTF_ERR;
+}
+
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/libctf/ctf-labels.c b/libctf/ctf-labels.c
index 16b111b14df..61742b3fb5f 100644
--- a/libctf/ctf-labels.c
+++ b/libctf/ctf-labels.c
@@ -48,12 +48,12 @@  ctf_label_topmost (ctf_dict_t *fp)
 
   if (num_labels == 0)
     {
-      (void) ctf_set_errno (fp, ECTF_NOLABELDATA);
+      (void) ctf_set_typed_errno (fp, ECTF_NOLABELDATA);
       return NULL;
     }
 
   if ((s = ctf_strraw (fp, (ctlp + num_labels - 1)->ctl_label)) == NULL)
-    (void) ctf_set_errno (fp, ECTF_CORRUPT);
+    (void) ctf_set_typed_errno (fp, ECTF_CORRUPT);
 
   return s;
 }
diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c
index 9babec2aa37..27d11c97893 100644
--- a/libctf/ctf-link.c
+++ b/libctf/ctf-link.c
@@ -243,8 +243,7 @@  ctf_link_lazy_open (ctf_dict_t *fp, ctf_link_input_t *input)
 #else
   ctf_err_warn (fp, 0, ECTF_NEEDSBFD, _("cannot open %s lazily"),
 		input->clin_filename);
-  ctf_set_errno (fp, ECTF_NEEDSBFD);
-  return -1;
+  return ctf_set_errno (fp, ECTF_NEEDSBFD);
 #endif
 
   /* Having no CTF sections is not an error.  We just don't need to do
@@ -257,8 +256,7 @@  ctf_link_lazy_open (ctf_dict_t *fp, ctf_link_input_t *input)
 
       ctf_err_warn (fp, 0, err, _("opening CTF %s failed"),
 		    input->clin_filename);
-      ctf_set_errno (fp, err);
-      return -1;
+      return ctf_set_errno (fp, err);
     }
 
   if ((count = ctf_archive_count (input->clin_arc)) == 0)
@@ -680,8 +678,7 @@  ctf_link_deduplicating_count_inputs (ctf_dict_t *fp, ctf_dynhash_t *cu_names,
     {
       ctf_err_warn (fp, 0, err, _("iteration error counting deduplicating "
 				  "CTF link inputs"));
-      ctf_set_errno (fp, err);
-      return -1;
+      return ctf_set_errno (fp, err);
     }
 
   if (!count)
@@ -1355,8 +1352,7 @@  ctf_link_empty_outputs (ctf_dict_t *fp)
     {
       fp->ctf_flags &= ~LCTF_LINKING;
       ctf_err_warn (fp, 1, err, _("iteration error removing old outputs"));
-      ctf_set_errno (fp, err);
-      return -1;
+      return ctf_set_errno (fp, err);
     }
   return 0;
 }
@@ -1536,8 +1532,7 @@  ctf_link (ctf_dict_t *fp, int flags)
 	{
 	  fp->ctf_flags &= ~LCTF_LINKING;
 	  ctf_err_warn (fp, 1, err, _("iteration error creating empty CUs"));
-	  ctf_set_errno (fp, err);
-	  return -1;
+	  return ctf_set_errno (fp, err);
 	}
     }
 
diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c
index c65849118cb..500b77ab868 100644
--- a/libctf/ctf-lookup.c
+++ b/libctf/ctf-lookup.c
@@ -143,7 +143,7 @@  ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child,
   ctf_id_t ntype, ptype;
 
   if (name == NULL)
-    return (ctf_set_errno (fp, EINVAL));
+    return (ctf_set_typed_errno (fp, EINVAL));
 
   for (p = name, end = name + strlen (name); *p != '\0'; p = q)
     {
@@ -292,7 +292,7 @@  ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child,
     }
 
   if (*p != '\0' || type == 0)
-    return (ctf_set_errno (fp, ECTF_SYNTAX));
+    return (ctf_set_typed_errno (fp, ECTF_SYNTAX));
 
   return type;
 
@@ -306,13 +306,13 @@  ctf_lookup_by_name_internal (ctf_dict_t *fp, ctf_dict_t *child,
       if (fp->ctf_pptrtab_typemax < fp->ctf_typemax)
 	{
 	  if (refresh_pptrtab (fp, fp->ctf_parent) < 0)
-	    return -1;			/* errno is set for us.  */
+	    return CTF_ERR;			/* errno is set for us.  */
 	}
 
       if ((ptype = ctf_lookup_by_name_internal (fp->ctf_parent, fp,
 						name)) != CTF_ERR)
 	return ptype;
-      return (ctf_set_errno (fp, ctf_errno (fp->ctf_parent)));
+      return (ctf_set_typed_errno (fp, ctf_errno (fp->ctf_parent)));
     }
 
   return CTF_ERR;
@@ -336,7 +336,7 @@  ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
 
   if ((fp = ctf_get_dict (fp, type)) == NULL)
     {
-      (void) ctf_set_errno (*fpp, ECTF_NOPARENT);
+      (void) ctf_set_typed_errno (*fpp, ECTF_NOPARENT);
       return NULL;
     }
 
@@ -351,7 +351,7 @@  ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
 	  *fpp = fp;
 	  return &dtd->dtd_data;
 	}
-      (void) ctf_set_errno (*fpp, ECTF_BADID);
+      (void) ctf_set_typed_errno (*fpp, ECTF_BADID);
       return NULL;
     }
 
@@ -364,7 +364,7 @@  ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type)
       return (LCTF_INDEX_TO_TYPEPTR (fp, idx));
     }
 
-  (void) ctf_set_errno (*fpp, ECTF_BADID);
+  (void) ctf_set_typed_errno (*fpp, ECTF_BADID);
   return NULL;
 }
 
@@ -407,10 +407,10 @@  ctf_lookup_variable (ctf_dict_t *fp, const char *name)
 
           if ((ptype = ctf_lookup_variable (fp->ctf_parent, name)) != CTF_ERR)
             return ptype;
-          return (ctf_set_errno (fp, ctf_errno (fp->ctf_parent)));
+          return (ctf_set_typed_errno (fp, ctf_errno (fp->ctf_parent)));
         }
 
-      return (ctf_set_errno (fp, ECTF_NOTYPEDAT));
+      return (ctf_set_typed_errno (fp, ECTF_NOTYPEDAT));
     }
 
   return ent->ctv_type;
@@ -622,13 +622,13 @@  ctf_lookup_symbol_idx (ctf_dict_t *fp, const char *symname)
 	  break;
 	default:
 	  ctf_set_errno (fp, ECTF_SYMTAB);
-	  return (unsigned long) -1;
+	  return CTF_ERR;
 	}
     }
 
   /* Searched everything, still not found.  */
 
-  return (unsigned long) -1;
+  return CTF_ERR;
 
  try_parent:
   if (fp->ctf_parent)
@@ -636,22 +636,22 @@  ctf_lookup_symbol_idx (ctf_dict_t *fp, const char *symname)
       unsigned long psym;
 
       if ((psym = ctf_lookup_symbol_idx (fp->ctf_parent, symname))
-          != (unsigned long) -1)
+          != CTF_ERR)
         return psym;
 
       ctf_set_errno (fp, ctf_errno (fp->ctf_parent));
-      return (unsigned long) -1;
+      return CTF_ERR;
     }
   else
     {
       ctf_set_errno (fp, err);
-      return (unsigned long) -1;
+      return CTF_ERR;
     }
 oom:
   ctf_set_errno (fp, ENOMEM);
   ctf_err_warn (fp, 0, ENOMEM, _("cannot allocate memory for symbol "
 				 "lookup hashtab"));
-  return (unsigned long) -1;
+  return CTF_ERR;
 
 }
 
@@ -673,7 +673,7 @@  ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
   if (!i)
     {
       if ((i = ctf_next_create ()) == NULL)
-	return ctf_set_errno (fp, ENOMEM);
+	return ctf_set_typed_errno (fp, ENOMEM);
 
       i->cu.ctn_fp = fp;
       i->ctn_iter_fun = (void (*) (void)) ctf_symbol_next;
@@ -682,10 +682,10 @@  ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
     }
 
   if ((void (*) (void)) ctf_symbol_next != i->ctn_iter_fun)
-    return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
+    return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFUN));
 
   if (fp != i->cu.ctn_fp)
-    return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
+    return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFP));
 
   /* We intentionally use raw access, not ctf_lookup_by_symbol, to avoid
      incurring additional sorting cost for unsorted symtypetabs coming from the
@@ -701,7 +701,7 @@  ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
       if (!dynh)
 	{
 	  ctf_next_destroy (i);
-	  return (ctf_set_errno (fp, ECTF_NEXT_END));
+	  return (ctf_set_typed_errno (fp, ECTF_NEXT_END));
 	}
 
       err = ctf_dynhash_next (dynh, &i->ctn_next, &dyn_name, &dyn_value);
@@ -710,7 +710,7 @@  ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
 	{
 	  ctf_next_destroy (i);
 	  *it = NULL;
-	  return ctf_set_errno (fp, err);
+	  return ctf_set_typed_errno (fp, err);
 	}
 
       *name = dyn_name;
@@ -786,7 +786,7 @@  ctf_symbol_next (ctf_dict_t *fp, ctf_next_t **it, const char **name,
  end:
   ctf_next_destroy (i);
   *it = NULL;
-  return (ctf_set_errno (fp, ECTF_NEXT_END));
+  return (ctf_set_typed_errno (fp, ECTF_NEXT_END));
 }
 
 /* A bsearch function for function and object index names.  */
@@ -821,7 +821,7 @@  ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
 	       "indexed symtypetab\n", symidx, symname);
 
   if (symname[0] == '\0')
-    return -1;					/* errno is set for us.  */
+    return CTF_ERR;					/* errno is set for us.  */
 
   if (is_function)
     {
@@ -835,7 +835,7 @@  ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
 	      == NULL)
 	    {
 	      ctf_err_warn (fp, 0, 0, _("cannot sort function symidx"));
-	      return -1;				/* errno is set for us.  */
+	      return CTF_ERR;				/* errno is set for us.  */
 	    }
 	}
       symtypetab = (uint32_t *) (fp->ctf_buf + hp->cth_funcoff);
@@ -855,7 +855,7 @@  ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
 	      == NULL)
 	    {
 	      ctf_err_warn (fp, 0, 0, _("cannot sort object symidx"));
-	      return -1;				/* errno is set for us. */
+	      return CTF_ERR;				/* errno is set for us. */
 	    }
 	}
 
@@ -878,7 +878,7 @@  ctf_try_lookup_indexed (ctf_dict_t *fp, unsigned long symidx,
 
   /* Should be impossible, but be paranoid.  */
   if ((idx - sxlate) > (ptrdiff_t) nidx)
-    return (ctf_set_errno (fp, ECTF_CORRUPT));
+    return (ctf_set_typed_errno (fp, ECTF_CORRUPT));
 
   ctf_dprintf ("Symbol %lx (%s) is of type %x\n", symidx, symname,
 	       symtypetab[*idx]);
@@ -1014,7 +1014,7 @@  ctf_lookup_by_sym_or_name (ctf_dict_t *fp, unsigned long symidx,
       return ret;
     }
   else
-    return (ctf_set_errno (fp, err));
+    return (ctf_set_typed_errno (fp, err));
 }
 
 /* Given a symbol table index, return the type of the function or data object
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index c20ff825d9a..12b4225a88a 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -426,7 +426,7 @@  ctf_type_next (ctf_dict_t *fp, ctf_next_t **it, int *flag, int want_hidden)
   if (!i)
     {
       if ((i = ctf_next_create ()) == NULL)
-	return ctf_set_errno (fp, ENOMEM);
+	return ctf_set_typed_errno (fp, ENOMEM);
 
       i->cu.ctn_fp = fp;
       i->ctn_type = 1;
@@ -435,10 +435,10 @@  ctf_type_next (ctf_dict_t *fp, ctf_next_t **it, int *flag, int want_hidden)
     }
 
   if ((void (*) (void)) ctf_type_next != i->ctn_iter_fun)
-    return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
+    return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFUN));
 
   if (fp != i->cu.ctn_fp)
-    return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
+    return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFP));
 
   while (i->ctn_type <= fp->ctf_typemax)
     {
@@ -456,7 +456,7 @@  ctf_type_next (ctf_dict_t *fp, ctf_next_t **it, int *flag, int want_hidden)
     }
   ctf_next_destroy (i);
   *it = NULL;
-  return ctf_set_errno (fp, ECTF_NEXT_END);
+  return ctf_set_typed_errno (fp, ECTF_NEXT_END);
 }
 
 /* Iterate over every variable in the given CTF dict, in arbitrary order.
@@ -494,12 +494,12 @@  ctf_variable_next (ctf_dict_t *fp, ctf_next_t **it, const char **name)
   ctf_next_t *i = *it;
 
   if ((fp->ctf_flags & LCTF_CHILD) && (fp->ctf_parent == NULL))
-    return (ctf_set_errno (fp, ECTF_NOPARENT));
+    return (ctf_set_typed_errno (fp, ECTF_NOPARENT));
 
   if (!i)
     {
       if ((i = ctf_next_create ()) == NULL)
-	return ctf_set_errno (fp, ENOMEM);
+	return ctf_set_typed_errno (fp, ENOMEM);
 
       i->cu.ctn_fp = fp;
       i->ctn_iter_fun = (void (*) (void)) ctf_variable_next;
@@ -509,10 +509,10 @@  ctf_variable_next (ctf_dict_t *fp, ctf_next_t **it, const char **name)
     }
 
   if ((void (*) (void)) ctf_variable_next != i->ctn_iter_fun)
-    return (ctf_set_errno (fp, ECTF_NEXT_WRONGFUN));
+    return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFUN));
 
   if (fp != i->cu.ctn_fp)
-    return (ctf_set_errno (fp, ECTF_NEXT_WRONGFP));
+    return (ctf_set_typed_errno (fp, ECTF_NEXT_WRONGFP));
 
   if (!(fp->ctf_flags & LCTF_RDWR))
     {
@@ -538,7 +538,7 @@  ctf_variable_next (ctf_dict_t *fp, ctf_next_t **it, const char **name)
  end_iter:
   ctf_next_destroy (i);
   *it = NULL;
-  return ctf_set_errno (fp, ECTF_NEXT_END);
+  return ctf_set_typed_errno (fp, ECTF_NEXT_END);
 }
 
 /* Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and
@@ -560,7 +560,7 @@  ctf_type_resolve (ctf_dict_t *fp, ctf_id_t type)
   const ctf_type_t *tp;
 
   if (type == 0)
-    return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
+    return (ctf_set_typed_errno (ofp, ECTF_NONREPRESENTABLE));
 
   while ((tp = ctf_lookup_by_id (&fp, type)) != NULL)
     {
@@ -575,18 +575,18 @@  ctf_type_resolve (ctf_dict_t *fp, ctf_id_t type)
 	    {
 	      ctf_err_warn (ofp, 0, ECTF_CORRUPT, _("type %lx cycle detected"),
 			    otype);
-	      return (ctf_set_errno (ofp, ECTF_CORRUPT));
+	      return (ctf_set_typed_errno (ofp, ECTF_CORRUPT));
 	    }
 	  prev = type;
 	  type = tp->ctt_type;
 	  break;
 	case CTF_K_UNKNOWN:
-	  return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
+	  return (ctf_set_typed_errno (ofp, ECTF_NONREPRESENTABLE));
 	default:
 	  return type;
 	}
       if (type == 0)
-	return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE));
+	return (ctf_set_typed_errno (ofp, ECTF_NONREPRESENTABLE));
     }
 
   return CTF_ERR;		/* errno is set for us.  */
@@ -612,7 +612,7 @@  ctf_type_resolve_unsliced (ctf_dict_t *fp, ctf_id_t type)
       ctf_id_t ret;
 
       if ((ret = ctf_type_reference (fp, type)) == CTF_ERR)
-	return (ctf_set_errno (ofp, ctf_errno (fp)));
+	return (ctf_set_typed_errno (ofp, ctf_errno (fp)));
       return ret;
     }
   return type;
@@ -836,7 +836,7 @@  ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
     }
 
   if (cd.cd_enomem)
-    (void) ctf_set_errno (fp, ENOMEM);
+    (void) ctf_set_typed_errno (fp, ENOMEM);
 
   buf = ctf_decl_buf (&cd);
 
@@ -854,7 +854,7 @@  ctf_type_lname (ctf_dict_t *fp, ctf_id_t type, char *buf, size_t len)
   size_t slen;
 
   if (str == NULL)
-    return CTF_ERR;			/* errno is set for us.  */
+    return -1;			/* errno is set for us.  */
 
   slen = strlen (str);
   snprintf (buf, len, "%s", str);
@@ -1139,7 +1139,7 @@  ctf_type_reference (ctf_dict_t *fp, ctf_id_t type)
 	return sp->cts_type;
       }
     default:
-      return (ctf_set_errno (ofp, ECTF_NOTREF));
+      return (ctf_set_typed_errno (ofp, ECTF_NOTREF));
     }
 }
 
@@ -1164,15 +1164,15 @@  ctf_type_pointer (ctf_dict_t *fp, ctf_id_t type)
     return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
 
   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
-    return (ctf_set_errno (ofp, ECTF_NOTYPE));
+    return (ctf_set_typed_errno (ofp, ECTF_NOTYPE));
 
   if (ctf_lookup_by_id (&fp, type) == NULL)
-    return (ctf_set_errno (ofp, ECTF_NOTYPE));
+    return (ctf_set_typed_errno (ofp, ECTF_NOTYPE));
 
   if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, type)]) != 0)
     return (LCTF_INDEX_TO_TYPE (fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
 
-  return (ctf_set_errno (ofp, ECTF_NOTYPE));
+  return (ctf_set_typed_errno (ofp, ECTF_NOTYPE));
 }
 
 /* Return the encoding for the specified INTEGER, FLOAT, or ENUM.  */
@@ -1557,8 +1557,7 @@  ctf_enum_value (ctf_dict_t *fp, ctf_id_t type, const char *name, int *valp)
 	}
     }
 
-  ctf_set_errno (ofp, ECTF_NOENUMNAM);
-  return -1;
+  return ctf_set_errno (ofp, ECTF_NOENUMNAM);
 }
 
 /* Given a type ID relating to a function type, return info on return types and
diff --git a/libctf/ctf-util.c b/libctf/ctf-util.c
index 9f83ab9ab0b..e0d412df390 100644
--- a/libctf/ctf-util.c
+++ b/libctf/ctf-util.c
@@ -255,16 +255,6 @@  ctf_set_open_errno (int *errp, int error)
   return NULL;
 }
 
-/* Store the specified error code into the CTF dict, and then return CTF_ERR /
-   -1 for the benefit of the caller. */
-
-unsigned long
-ctf_set_errno (ctf_dict_t *fp, int err)
-{
-  fp->ctf_errno = err;
-  return CTF_ERR;
-}
-
 /* Create a ctf_next_t.  */
 
 ctf_next_t *