]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf: split out compatibility code
authorNick Alcock <nick.alcock@oracle.com>
Thu, 24 Apr 2025 12:44:36 +0000 (13:44 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 17:07:41 +0000 (18:07 +0100)
The compatibility-opening code is quite voluminous, and is stuck right in
the middle of ctf-open.c, rather interfering with maintenance.  Split it
out into a new ctf-open-compat.c.  (Since it is not yet upgraded to support
v4, the new file is not added to the build system yet: indeed, even the
calls to it haven't been diked out at this stage.)

libctf/ctf-open-compat.c [new file with mode: 0644]
libctf/ctf-open.c

diff --git a/libctf/ctf-open-compat.c b/libctf/ctf-open-compat.c
new file mode 100644 (file)
index 0000000..4e5b994
--- /dev/null
@@ -0,0 +1,538 @@
+/* Opening CTF files: back-compatibility.
+   (TODO: not yet implemented, not yet tied in to build system.)
+   Copyright (C) 2019-2025 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctf-impl.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+#include "swap.h"
+#include <bfd.h>
+#include <zlib.h>
+
+/* Upgrade the header to CTF_VERSION_4.  The upgrade is done in-place,
+   end-to-start. UPTODO: redo this */
+void
+upgrade_header_v2 (ctf_header_t *hp)
+{
+  ctf_header_v2_t *oldhp = (ctf_header_v2_t *) hp;
+
+  hp->cth_strlen = oldhp->cth_strlen;
+  hp->cth_stroff = oldhp->cth_stroff;
+  hp->cth_typeoff = oldhp->cth_typeoff;
+  hp->cth_varoff = oldhp->cth_varoff;
+  hp->cth_funcidxoff = hp->cth_varoff;         /* No index sections.  */
+  hp->cth_objtidxoff = hp->cth_funcidxoff;
+  hp->cth_funcoff = oldhp->cth_funcoff;
+  hp->cth_objtoff = oldhp->cth_objtoff;
+  hp->cth_lbloff = oldhp->cth_lbloff;
+  hp->cth_parent_strlen = 0;                   /* Strings start at offset 0.  */
+  hp->cth_cu_name = 0;                         /* No CU name.  */
+}
+
+/* Ditto, for CTFv3. UPTODO: redo this */
+void
+upgrade_header_v3 (ctf_header_t *hp)
+{
+  ctf_header_v3_t *oldhp = (ctf_header_v3_t *) hp;
+
+  hp->btf.bth_str_len = oldhp->cth_strlen;
+  hp->btf.bth_str_off = oldhp->cth_stroff;
+  hp->btf.bth_type_off = oldhp->cth_typeoff;
+  hp->cth_funcidx_off = oldhp->cth_funcidxoff;
+  hp->cth_objtidx_off = oldhp->cth_objtidxoff;
+  hp->cth_func_off = oldhp->cth_funcoff;
+  hp->cth_objt_off = oldhp->cth_objtoff;
+  /* lens */
+  hp->cth_lbloff = oldhp->cth_lbloff;
+  hp->cth_parent_strlen = 0;                   /* Strings start at offset 0.  */
+  hp->cth_cu_name = oldhp->cth_cuname;
+  hp->cth_parent_name = oldhp->cth_parname;
+  hp->cth_parent_ntypes = 0;
+}
+
+/* Set the version of the CTF file. */
+
+/* When this is reset, LCTF_* changes behaviour, but there is no guarantee that
+   the variable data list associated with each type has been upgraded: the
+   caller must ensure this has been done in advance.  */
+
+static void
+ctf_set_version (ctf_dict_t *fp, ctf_header_t *cth, int ctf_version)
+{
+  fp->ctf_version = ctf_version;
+  cth->cth_version = ctf_version;
+  fp->ctf_dictops = &ctf_dictops[ctf_version];
+}
+
+/* Upgrade the type table to CTF_VERSION_3 (really CTF_VERSION_1_UPGRADED_3)
+   from CTF_VERSION_1.
+
+   The upgrade is not done in-place: the ctf_base is moved.  ctf_strptr() must
+   not be called before reallocation is complete.
+
+   Sections not checked here due to nonexistence or nonpopulated state in older
+   formats: objtidx, funcidx.
+
+   Type kinds not checked here due to nonexistence in older formats:
+      CTF_K_SLICE.  */
+static int
+upgrade_types_v1 (ctf_dict_t *fp, ctf_header_t *cth)
+{
+  const ctf_type_v1_t *tbuf;
+  const ctf_type_v1_t *tend;
+  unsigned char *ctf_base, *old_ctf_base = (unsigned char *) fp->ctf_dynbase;
+  ctf_type_t *t2buf;
+
+  ssize_t increase = 0, size, increment, v2increment, vbytes, v2bytes;
+  const ctf_type_v1_t *tp;
+  ctf_type_t *t2p;
+
+  tbuf = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_typeoff);
+  tend = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_stroff);
+
+  /* This is a two-pass process.
+
+     First, figure out the new type-section size needed.  (It is possible,
+     in theory, for it to be less than the old size, but this is very
+     unlikely.  It cannot be so small that cth_typeoff ends up of negative
+     size.  We validate this with an assertion below.)
+
+     We must cater not only for changes in vlen and types sizes but also
+     for changes in 'increment', which happen because v2 places some types
+     into ctf_stype_t where v1 would be forced to use the larger non-stype.  */
+
+  for (tp = tbuf; tp < tend;
+       tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes))
+    {
+      unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
+      unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
+
+      size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
+      vbytes = get_vbytes_v1 (fp, kind, size, vlen);
+
+      get_ctt_size_v2_unconverted (fp, (const ctf_type_t *) tp, NULL,
+                                  &v2increment);
+      v2bytes = get_vbytes_v2 (fp, kind, size, vlen);
+
+      if ((vbytes < 0) || (size < 0))
+       return ECTF_CORRUPT;
+
+      increase += v2increment - increment;     /* May be negative.  */
+      increase += v2bytes - vbytes;
+    }
+
+  /* Allocate enough room for the new buffer, then copy everything but the type
+     section into place, and reset the base accordingly.  Leave the version
+     number unchanged, so that LCTF_INFO_* still works on the
+     as-yet-untranslated type info.  */
+
+  if ((ctf_base = malloc (fp->ctf_size + increase)) == NULL)
+    return ECTF_ZALLOC;
+
+  /* Start at ctf_buf, not ctf_base, to squeeze out the original header: we
+     never use it and it is unconverted.  */
+
+  memcpy (ctf_base, fp->ctf_buf, cth->cth_typeoff);
+  memcpy (ctf_base + cth->cth_stroff + increase,
+         fp->ctf_buf + cth->cth_stroff, cth->cth_strlen);
+
+  memset (ctf_base + cth->cth_typeoff, 0, cth->cth_stroff - cth->cth_typeoff
+         + increase);
+
+  cth->cth_stroff += increase;
+  fp->ctf_size += increase;
+  assert (cth->cth_stroff >= cth->cth_typeoff);
+  fp->ctf_base = ctf_base;
+  fp->ctf_buf = ctf_base;
+  fp->ctf_dynbase = ctf_base;
+  ctf_set_base (fp, cth, ctf_base);
+
+  t2buf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff);
+
+  /* Iterate through all the types again, upgrading them.
+
+     Everything that hasn't changed can just be outright memcpy()ed.
+     Things that have changed need field-by-field consideration.  */
+
+  for (tp = tbuf, t2p = t2buf; tp < tend;
+       tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes),
+       t2p = (ctf_type_t *) ((uintptr_t) t2p + v2increment + v2bytes))
+    {
+      unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
+      int isroot = CTF_V1_INFO_ISROOT (tp->ctt_info);
+      unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
+      ssize_t v2size;
+      void *vdata, *v2data;
+
+      size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
+      vbytes = get_vbytes_v1 (fp, kind, size, vlen);
+
+      t2p->ctt_name = tp->ctt_name;
+      t2p->ctt_info = CTF_TYPE_INFO (kind, isroot, vlen);
+
+      switch (kind)
+       {
+       case CTF_K_FUNCTION:
+       case CTF_K_FORWARD:
+       case CTF_K_TYPEDEF:
+       case CTF_K_POINTER:
+       case CTF_K_VOLATILE:
+       case CTF_K_CONST:
+       case CTF_K_RESTRICT:
+         t2p->ctt_type = tp->ctt_type;
+         break;
+       case CTF_K_INTEGER:
+       case CTF_K_FLOAT:
+       case CTF_K_ARRAY:
+       case CTF_K_STRUCT:
+       case CTF_K_UNION:
+       case CTF_K_ENUM:
+       case CTF_K_UNKNOWN:
+         if ((size_t) size <= CTF_MAX_SIZE)
+           t2p->ctt_size = size;
+         else
+           {
+             t2p->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+             t2p->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+           }
+         break;
+       }
+
+      v2size = get_ctt_size_v2 (fp, t2p, NULL, &v2increment);
+      v2bytes = get_vbytes_v2 (fp, kind, v2size, vlen);
+
+      /* Catch out-of-sync get_ctt_size_*().  The count goes wrong if
+        these are not identical (and having them different makes no
+        sense semantically).  */
+
+      assert (size == v2size);
+
+      /* Now the varlen info.  */
+
+      vdata = (void *) ((uintptr_t) tp + increment);
+      v2data = (void *) ((uintptr_t) t2p + v2increment);
+
+      switch (kind)
+       {
+       case CTF_K_ARRAY:
+         {
+           const ctf_array_v1_t *ap = (const ctf_array_v1_t *) vdata;
+           ctf_array_t *a2p = (ctf_array_t *) v2data;
+
+           a2p->cta_contents = ap->cta_contents;
+           a2p->cta_index = ap->cta_index;
+           a2p->cta_nelems = ap->cta_nelems;
+           break;
+         }
+       case CTF_K_STRUCT:
+       case CTF_K_UNION:
+         {
+           ctf_member_t tmp;
+           const ctf_member_v1_t *m1 = (const ctf_member_v1_t *) vdata;
+           const ctf_lmember_v1_t *lm1 = (const ctf_lmember_v1_t *) m1;
+           ctf_member_t *m2 = (ctf_member_t *) v2data;
+           ctf_lmember_t *lm2 = (ctf_lmember_t *) m2;
+           unsigned long i;
+
+           /* We walk all four pointers forward, but only reference the two
+              that are valid for the given size, to avoid quadruplicating all
+              the code.  */
+
+           for (i = vlen; i != 0; i--, m1++, lm1++, m2++, lm2++)
+             {
+               size_t offset;
+               if (size < CTF_LSTRUCT_THRESH_V1)
+                 {
+                   offset = m1->ctm_offset;
+                   tmp.ctm_name = m1->ctm_name;
+                   tmp.ctm_type = m1->ctm_type;
+                 }
+               else
+                 {
+                   offset = CTF_LMEM_OFFSET (lm1);
+                   tmp.ctm_name = lm1->ctlm_name;
+                   tmp.ctm_type = lm1->ctlm_type;
+                 }
+               if (size < CTF_LSTRUCT_THRESH)
+                 {
+                   m2->ctm_name = tmp.ctm_name;
+                   m2->ctm_type = tmp.ctm_type;
+                   m2->ctm_offset = offset;
+                 }
+               else
+                 {
+                   lm2->ctlm_name = tmp.ctm_name;
+                   lm2->ctlm_type = tmp.ctm_type;
+                   lm2->ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (offset);
+                   lm2->ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (offset);
+                 }
+             }
+           break;
+         }
+       case CTF_K_FUNCTION:
+         {
+           unsigned long i;
+           unsigned short *a1 = (unsigned short *) vdata;
+           uint32_t *a2 = (uint32_t *) v2data;
+
+           for (i = vlen; i != 0; i--, a1++, a2++)
+             *a2 = *a1;
+         }
+       /* FALLTHRU */
+       default:
+         /* Catch out-of-sync get_vbytes_*().  */
+         assert (vbytes == v2bytes);
+         memcpy (v2data, vdata, vbytes);
+       }
+    }
+
+  /* Verify that the entire region was converted.  If not, we are either
+     converting too much, or too little (leading to a buffer overrun either here
+     or at read time, in init_static_types().) */
+
+  assert ((size_t) t2p - (size_t) fp->ctf_buf == cth->cth_stroff);
+
+  ctf_set_version (fp, cth, CTF_VERSION_1_UPGRADED_3);
+  free (old_ctf_base);
+
+  return 0;
+}
+
+/* Upgrade from any earlier version.  */
+static int
+upgrade_types (ctf_dict_t *fp, ctf_header_t *cth)
+{
+  switch (cth->cth_version)
+    {
+      /* v1 requires a full pass and reformatting.  */
+    case CTF_VERSION_1:
+      upgrade_types_v1 (fp, cth);
+      /* FALLTHRU */
+      /* Already-converted v1 is just like later versions except that its
+        parent/child boundary is unchanged (and much lower).  */
+
+    case CTF_VERSION_1_UPGRADED_3:
+      fp->ctf_header->cth_parent_ntypes = CTF_MAX_PTYPE_V1;
+      break;
+
+      /* v2 and v3 are currently just the same as v4 except for new types and
+        sections: no upgrading required.
+
+        UPTODO: this is really going to change.  */
+    case CTF_VERSION_2: ;
+    case CTF_VERSION_3: ;
+      fp->ctf_header->cth_parent_ntypes = CTF_MAX_PTYPE;
+      /* FALLTHRU */
+    }
+  return 0;
+}
+
+
+/* Flip the endianness of the v3 type section, a tagged array of ctf_type or
+   ctf_stype followed by variable data.  */
+
+static int
+flip_types_v3 (ctf_dict_t *fp, void *start, size_t len, int to_foreign)
+{
+  ctf_type_t *t = start;
+
+  while ((uintptr_t) t < ((uintptr_t) start) + len)
+    {
+      uint32_t kind;
+      size_t size;
+      uint32_t vlen;
+      size_t vbytes;
+
+      if (to_foreign)
+       {
+         kind = CTF_V2_INFO_KIND (t->ctt_info);
+         size = t->ctt_size;
+         vlen = CTF_V2_INFO_VLEN (t->ctt_info);
+         vbytes = get_vbytes_v2 (fp, kind, size, vlen);
+       }
+
+      swap_thing (t->ctt_name);
+      swap_thing (t->ctt_info);
+      swap_thing (t->ctt_size);
+
+      if (!to_foreign)
+       {
+         kind = CTF_V2_INFO_KIND (t->ctt_info);
+         size = t->ctt_size;
+         vlen = CTF_V2_INFO_VLEN (t->ctt_info);
+         vbytes = get_vbytes_v2 (fp, kind, size, vlen);
+       }
+
+      if (_libctf_unlikely_ (size == CTF_LSIZE_SENT))
+       {
+         if (to_foreign)
+           size = CTF_TYPE_LSIZE (t);
+
+         swap_thing (t->ctt_lsizehi);
+         swap_thing (t->ctt_lsizelo);
+
+         if (!to_foreign)
+           size = CTF_TYPE_LSIZE (t);
+
+         t = (ctf_type_t *) ((uintptr_t) t + sizeof (ctf_type_t));
+       }
+      else
+       t = (ctf_type_t *) ((uintptr_t) t + sizeof (ctf_stype_t));
+
+      switch (kind)
+       {
+       case CTF_K_FORWARD:
+       case CTF_K_UNKNOWN:
+       case CTF_K_POINTER:
+       case CTF_K_TYPEDEF:
+       case CTF_K_VOLATILE:
+       case CTF_K_CONST:
+       case CTF_K_RESTRICT:
+         /* These types have no vlen data to swap.  */
+         assert (vbytes == 0);
+         break;
+
+       case CTF_K_INTEGER:
+       case CTF_K_FLOAT:
+         {
+           /* These types have a single uint32_t.  */
+
+           uint32_t *item = (uint32_t *) t;
+
+           swap_thing (*item);
+           break;
+         }
+
+       case CTF_K_FUNCTION:
+         {
+           /* This type has a bunch of uint32_ts.  */
+
+           uint32_t *item = (uint32_t *) t;
+           ssize_t i;
+
+           for (i = vlen; i > 0; item++, i--)
+             swap_thing (*item);
+           break;
+         }
+
+       case CTF_K_ARRAY:
+         {
+           /* This has a single ctf_array_t.  */
+
+           ctf_array_t *a = (ctf_array_t *) t;
+
+           assert (vbytes == sizeof (ctf_array_t));
+           swap_thing (a->cta_contents);
+           swap_thing (a->cta_index);
+           swap_thing (a->cta_nelems);
+
+           break;
+         }
+
+       case CTF_K_SLICE:
+         {
+           /* This has a single ctf_slice_t.  */
+
+           ctf_slice_t *s = (ctf_slice_t *) t;
+
+           assert (vbytes == sizeof (ctf_slice_t));
+           swap_thing (s->cts_type);
+           swap_thing (s->cts_offset);
+           swap_thing (s->cts_bits);
+
+           break;
+         }
+
+       case CTF_K_STRUCT:
+       case CTF_K_UNION:
+         {
+           /* This has an array of ctf_member or ctf_lmember, depending on
+              size.  We could consider it to be a simple array of uint32_t,
+              but for safety's sake in case these structures ever acquire
+              non-uint32_t members, do it member by member.  */
+
+           if (_libctf_unlikely_ (size >= CTF_LSTRUCT_THRESH))
+             {
+               ctf_lmember_t *lm = (ctf_lmember_t *) t;
+               ssize_t i;
+               for (i = vlen; i > 0; i--, lm++)
+                 {
+                   swap_thing (lm->ctlm_name);
+                   swap_thing (lm->ctlm_offsethi);
+                   swap_thing (lm->ctlm_type);
+                   swap_thing (lm->ctlm_offsetlo);
+                 }
+             }
+           else
+             {
+               ctf_member_t *m = (ctf_member_t *) t;
+               ssize_t i;
+               for (i = vlen; i > 0; i--, m++)
+                 {
+                   swap_thing (m->ctm_name);
+                   swap_thing (m->ctm_offset);
+                   swap_thing (m->ctm_type);
+                 }
+             }
+           break;
+         }
+
+       case CTF_K_ENUM:
+         {
+           /* This has an array of ctf_enum_t.  */
+
+           ctf_enum_t *item = (ctf_enum_t *) t;
+           ssize_t i;
+
+           for (i = vlen; i > 0; item++, i--)
+             {
+               swap_thing (item->cte_name);
+               swap_thing (item->cte_value);
+             }
+           break;
+         }
+       default:
+         ctf_err_warn (fp, 0, ECTF_CORRUPT,
+                       _("unhandled CTF kind in endianness conversion: %x"),
+                       kind);
+         return ECTF_CORRUPT;
+       }
+
+      t = (ctf_type_t *) ((uintptr_t) t + vbytes);
+    }
+
+  return 0;
+}
+
+/* Flip the endianness of the v3 variable section, an array of ctf_varent_t.  */
+
+static void
+flip_vars_v3 (void *start, size_t len)
+{
+  ctf_varent_t *var = start;
+  ssize_t i;
+
+  for (i = len / sizeof (struct ctf_varent); i > 0; var++, i--)
+    {
+      swap_thing (var->ctv_name);
+      swap_thing (var->ctv_type);
+    }
+}
+
index 600fd8a21926b306fb740fdb8f140d7db9c40e6b..fb8a752ca53044b2fb699747696b864b10045aef 100644 (file)
@@ -384,325 +384,7 @@ ctf_set_base (ctf_dict_t *fp, const ctf_header_t *hp, unsigned char *base)
     ctf_dprintf ("ctf_set_base: parent name %s (label %s)\n",
               fp->ctf_parname,
               fp->ctf_parlabel ? fp->ctf_parlabel : "<NULL>");
-}
-
-/* Set the version of the CTF file. */
-
-/* When this is reset, LCTF_* changes behaviour, but there is no guarantee that
-   the variable data list associated with each type has been upgraded: the
-   caller must ensure this has been done in advance.  */
-
-static void
-ctf_set_version (ctf_dict_t *fp, ctf_header_t *cth, int ctf_version)
-{
-  fp->ctf_version = ctf_version;
-  cth->cth_version = ctf_version;
-  fp->ctf_dictops = &ctf_dictops[ctf_version];
-}
-
-
-/* Upgrade the header to CTF_VERSION_4.  The upgrade is done in-place,
-   end-to-start.  */
-static void
-upgrade_header_v2 (ctf_header_t *hp)
-{
-  ctf_header_v2_t *oldhp = (ctf_header_v2_t *) hp;
-
-  hp->cth_strlen = oldhp->cth_strlen;
-  hp->cth_stroff = oldhp->cth_stroff;
-  hp->cth_typeoff = oldhp->cth_typeoff;
-  hp->cth_varoff = oldhp->cth_varoff;
-  hp->cth_funcidxoff = hp->cth_varoff;         /* No index sections.  */
-  hp->cth_objtidxoff = hp->cth_funcidxoff;
-  hp->cth_funcoff = oldhp->cth_funcoff;
-  hp->cth_objtoff = oldhp->cth_objtoff;
-  hp->cth_lbloff = oldhp->cth_lbloff;
-  hp->cth_parent_strlen = 0;                   /* Strings start at offset 0.  */
-  hp->cth_cuname = 0;                          /* No CU name.  */
-}
-
-/* Ditto, for CTFv3.  */
-static void
-upgrade_header_v3 (ctf_header_t *hp)
-{
-  ctf_header_v3_t *oldhp = (ctf_header_v3_t *) hp;
-
-  hp->cth_strlen = oldhp->cth_strlen;
-  hp->cth_stroff = oldhp->cth_stroff;
-  hp->cth_typeoff = oldhp->cth_typeoff;
-  hp->cth_varoff = oldhp->cth_varoff;
-  hp->cth_funcidxoff = oldhp->cth_funcidxoff;
-  hp->cth_objtidxoff = oldhp->cth_objtidxoff;
-  hp->cth_funcoff = oldhp->cth_funcoff;
-  hp->cth_objtoff = oldhp->cth_objtoff;
-  hp->cth_lbloff = oldhp->cth_lbloff;
-  hp->cth_parent_strlen = 0;                   /* Strings start at offset 0.  */
-  hp->cth_cuname = oldhp->cth_cuname;
-  hp->cth_parname = oldhp->cth_parname;
-  hp->cth_parlabel = oldhp->cth_parlabel;
-}
-
-/* Upgrade the type table to CTF_VERSION_3 (really CTF_VERSION_1_UPGRADED_3)
-   from CTF_VERSION_1.
-
-   The upgrade is not done in-place: the ctf_base is moved.  ctf_strptr() must
-   not be called before reallocation is complete.
-
-   Sections not checked here due to nonexistence or nonpopulated state in older
-   formats: objtidx, funcidx.
-
-   Type kinds not checked here due to nonexistence in older formats:
-      CTF_K_SLICE.  */
-static int
-upgrade_types_v1 (ctf_dict_t *fp, ctf_header_t *cth)
-{
-  const ctf_type_v1_t *tbuf;
-  const ctf_type_v1_t *tend;
-  unsigned char *ctf_base, *old_ctf_base = (unsigned char *) fp->ctf_dynbase;
-  ctf_type_t *t2buf;
-
-  ssize_t increase = 0, size, increment, v2increment, vbytes, v2bytes;
-  const ctf_type_v1_t *tp;
-  ctf_type_t *t2p;
-
-  tbuf = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_typeoff);
-  tend = (ctf_type_v1_t *) (fp->ctf_buf + cth->cth_stroff);
-
-  /* This is a two-pass process.
-
-     First, figure out the new type-section size needed.  (It is possible,
-     in theory, for it to be less than the old size, but this is very
-     unlikely.  It cannot be so small that cth_typeoff ends up of negative
-     size.  We validate this with an assertion below.)
-
-     We must cater not only for changes in vlen and types sizes but also
-     for changes in 'increment', which happen because v2 places some types
-     into ctf_stype_t where v1 would be forced to use the larger non-stype.  */
-
-  for (tp = tbuf; tp < tend;
-       tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes))
-    {
-      unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
-      unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
-
-      size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
-      vbytes = get_vbytes_v1 (fp, kind, size, vlen);
-
-      get_ctt_size_v2_unconverted (fp, (const ctf_type_t *) tp, NULL,
-                                  &v2increment);
-      v2bytes = get_vbytes_v2 (fp, kind, size, vlen);
-
-      if ((vbytes < 0) || (size < 0))
-       return ECTF_CORRUPT;
-
-      increase += v2increment - increment;     /* May be negative.  */
-      increase += v2bytes - vbytes;
-    }
-
-  /* Allocate enough room for the new buffer, then copy everything but the type
-     section into place, and reset the base accordingly.  Leave the version
-     number unchanged, so that LCTF_INFO_* still works on the
-     as-yet-untranslated type info.  */
-
-  if ((ctf_base = malloc (fp->ctf_size + increase)) == NULL)
-    return ECTF_ZALLOC;
-
-  /* Start at ctf_buf, not ctf_base, to squeeze out the original header: we
-     never use it and it is unconverted.  */
-
-  memcpy (ctf_base, fp->ctf_buf, cth->cth_typeoff);
-  memcpy (ctf_base + cth->cth_stroff + increase,
-         fp->ctf_buf + cth->cth_stroff, cth->cth_strlen);
-
-  memset (ctf_base + cth->cth_typeoff, 0, cth->cth_stroff - cth->cth_typeoff
-         + increase);
-
-  cth->cth_stroff += increase;
-  fp->ctf_size += increase;
-  assert (cth->cth_stroff >= cth->cth_typeoff);
-  fp->ctf_base = ctf_base;
-  fp->ctf_buf = ctf_base;
-  fp->ctf_dynbase = ctf_base;
-  ctf_set_base (fp, cth, ctf_base);
-
-  t2buf = (ctf_type_t *) (fp->ctf_buf + cth->cth_typeoff);
-
-  /* Iterate through all the types again, upgrading them.
-
-     Everything that hasn't changed can just be outright memcpy()ed.
-     Things that have changed need field-by-field consideration.  */
-
-  for (tp = tbuf, t2p = t2buf; tp < tend;
-       tp = (ctf_type_v1_t *) ((uintptr_t) tp + increment + vbytes),
-       t2p = (ctf_type_t *) ((uintptr_t) t2p + v2increment + v2bytes))
-    {
-      unsigned short kind = CTF_V1_INFO_KIND (tp->ctt_info);
-      int isroot = CTF_V1_INFO_ISROOT (tp->ctt_info);
-      unsigned long vlen = CTF_V1_INFO_VLEN (tp->ctt_info);
-      ssize_t v2size;
-      void *vdata, *v2data;
-
-      size = get_ctt_size_v1 (fp, (const ctf_type_t *) tp, NULL, &increment);
-      vbytes = get_vbytes_v1 (fp, kind, size, vlen);
-
-      t2p->ctt_name = tp->ctt_name;
-      t2p->ctt_info = CTF_TYPE_INFO (kind, isroot, vlen);
-
-      switch (kind)
-       {
-       case CTF_K_FUNCTION:
-       case CTF_K_FORWARD:
-       case CTF_K_TYPEDEF:
-       case CTF_K_POINTER:
-       case CTF_K_VOLATILE:
-       case CTF_K_CONST:
-       case CTF_K_RESTRICT:
-         t2p->ctt_type = tp->ctt_type;
-         break;
-       case CTF_K_INTEGER:
-       case CTF_K_FLOAT:
-       case CTF_K_ARRAY:
-       case CTF_K_STRUCT:
-       case CTF_K_UNION:
-       case CTF_K_ENUM:
-       case CTF_K_UNKNOWN:
-         if ((size_t) size <= CTF_MAX_SIZE)
-           t2p->ctt_size = size;
-         else
-           {
-             t2p->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
-             t2p->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
-           }
-         break;
-       }
-
-      v2size = get_ctt_size_v2 (fp, t2p, NULL, &v2increment);
-      v2bytes = get_vbytes_v2 (fp, kind, v2size, vlen);
-
-      /* Catch out-of-sync get_ctt_size_*().  The count goes wrong if
-        these are not identical (and having them different makes no
-        sense semantically).  */
-
-      assert (size == v2size);
 
-      /* Now the varlen info.  */
-
-      vdata = (void *) ((uintptr_t) tp + increment);
-      v2data = (void *) ((uintptr_t) t2p + v2increment);
-
-      switch (kind)
-       {
-       case CTF_K_ARRAY:
-         {
-           const ctf_array_v1_t *ap = (const ctf_array_v1_t *) vdata;
-           ctf_array_t *a2p = (ctf_array_t *) v2data;
-
-           a2p->cta_contents = ap->cta_contents;
-           a2p->cta_index = ap->cta_index;
-           a2p->cta_nelems = ap->cta_nelems;
-           break;
-         }
-       case CTF_K_STRUCT:
-       case CTF_K_UNION:
-         {
-           ctf_member_t tmp;
-           const ctf_member_v1_t *m1 = (const ctf_member_v1_t *) vdata;
-           const ctf_lmember_v1_t *lm1 = (const ctf_lmember_v1_t *) m1;
-           ctf_member_t *m2 = (ctf_member_t *) v2data;
-           ctf_lmember_t *lm2 = (ctf_lmember_t *) m2;
-           unsigned long i;
-
-           /* We walk all four pointers forward, but only reference the two
-              that are valid for the given size, to avoid quadruplicating all
-              the code.  */
-
-           for (i = vlen; i != 0; i--, m1++, lm1++, m2++, lm2++)
-             {
-               size_t offset;
-               if (size < CTF_LSTRUCT_THRESH_V1)
-                 {
-                   offset = m1->ctm_offset;
-                   tmp.ctm_name = m1->ctm_name;
-                   tmp.ctm_type = m1->ctm_type;
-                 }
-               else
-                 {
-                   offset = CTF_LMEM_OFFSET (lm1);
-                   tmp.ctm_name = lm1->ctlm_name;
-                   tmp.ctm_type = lm1->ctlm_type;
-                 }
-               if (size < CTF_LSTRUCT_THRESH)
-                 {
-                   m2->ctm_name = tmp.ctm_name;
-                   m2->ctm_type = tmp.ctm_type;
-                   m2->ctm_offset = offset;
-                 }
-               else
-                 {
-                   lm2->ctlm_name = tmp.ctm_name;
-                   lm2->ctlm_type = tmp.ctm_type;
-                   lm2->ctlm_offsethi = CTF_OFFSET_TO_LMEMHI (offset);
-                   lm2->ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO (offset);
-                 }
-             }
-           break;
-         }
-       case CTF_K_FUNCTION:
-         {
-           unsigned long i;
-           unsigned short *a1 = (unsigned short *) vdata;
-           uint32_t *a2 = (uint32_t *) v2data;
-
-           for (i = vlen; i != 0; i--, a1++, a2++)
-             *a2 = *a1;
-         }
-       /* FALLTHRU */
-       default:
-         /* Catch out-of-sync get_vbytes_*().  */
-         assert (vbytes == v2bytes);
-         memcpy (v2data, vdata, vbytes);
-       }
-    }
-
-  /* Verify that the entire region was converted.  If not, we are either
-     converting too much, or too little (leading to a buffer overrun either here
-     or at read time, in init_static_types().) */
-
-  assert ((size_t) t2p - (size_t) fp->ctf_buf == cth->cth_stroff);
-
-  ctf_set_version (fp, cth, CTF_VERSION_1_UPGRADED_3);
-  free (old_ctf_base);
-
-  return 0;
-}
-
-/* Upgrade from any earlier version.  */
-static int
-upgrade_types (ctf_dict_t *fp, ctf_header_t *cth)
-{
-  switch (cth->cth_version)
-    {
-      /* v1 requires a full pass and reformatting.  */
-    case CTF_VERSION_1:
-      upgrade_types_v1 (fp, cth);
-      /* FALLTHRU */
-      /* Already-converted v1 is just like later versions except that its
-        parent/child boundary is unchanged (and much lower).  */
-
-    case CTF_VERSION_1_UPGRADED_3:
-      fp->ctf_header->cth_parent_typemax = CTF_MAX_PTYPE_V1;
-      break;
-
-      /* v2 and v3 are currently just the same as v4 except for new types and
-        sections: no upgrading required.
-
-        UPTODO: this is really going to change.  */
-    case CTF_VERSION_2: ;
-    case CTF_VERSION_3: ;
-      fp->ctf_header->cth_parent_typemax = CTF_MAX_PTYPE;
-      /* FALLTHRU */
-    }
-  return 0;
 }
 
 static int