]> Git Repo - binutils.git/blobdiff - libctf/ctf-open.c
Automatic date update in version.in
[binutils.git] / libctf / ctf-open.c
index ecf27eeeb21da6ef6ecf5bd44c7bdc480154a3d7..f0e203e0a16d7b6533a0db8cbc53f9d866cec2dd 100644 (file)
@@ -1,5 +1,5 @@
 /* Opening CTF files.
 /* Opening CTF files.
-   Copyright (C) 2019-2020 Free Software Foundation, Inc.
+   Copyright (C) 2019-2022 Free Software Foundation, Inc.
 
    This file is part of libctf.
 
 
    This file is part of libctf.
 
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <sys/types.h>
 #include <elf.h>
 #include <string.h>
 #include <sys/types.h>
 #include <elf.h>
-#include <assert.h>
 #include "swap.h"
 #include <bfd.h>
 #include <zlib.h>
 #include "swap.h"
 #include <bfd.h>
 #include <zlib.h>
@@ -227,7 +226,10 @@ static const ctf_dictops_t ctf_dictops[] = {
    symtypetabs come from the compiler, and all the linker does is iteration over
    all entries, which doesn't need this initialization.)
 
    symtypetabs come from the compiler, and all the linker does is iteration over
    all entries, which doesn't need this initialization.)
 
-   The SP symbol table section may be NULL if there is no symtab.  */
+   The SP symbol table section may be NULL if there is no symtab.
+
+   If init_symtab works on one call, it cannot fail on future calls to the same
+   fp: ctf_symsect_endianness relies on this.  */
 
 static int
 init_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp)
 
 static int
 init_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp)
@@ -236,7 +238,7 @@ init_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp)
   int skip_func_info = 0;
   int i;
   uint32_t *xp = fp->ctf_sxlate;
   int skip_func_info = 0;
   int i;
   uint32_t *xp = fp->ctf_sxlate;
-  uint32_t *xend = xp + fp->ctf_nsyms;
+  uint32_t *xend = PTR_ADD (xp, fp->ctf_nsyms);
 
   uint32_t objtoff = hp->cth_objtoff;
   uint32_t funcoff = hp->cth_funcoff;
 
   uint32_t objtoff = hp->cth_objtoff;
   uint32_t funcoff = hp->cth_funcoff;
@@ -290,6 +292,10 @@ init_symtab (ctf_dict_t *fp, const ctf_header_t *hp, const ctf_sect_t *sp)
          return ECTF_SYMTAB;
        }
 
          return ECTF_SYMTAB;
        }
 
+      /* This call may be led astray if our idea of the symtab's endianness is
+        wrong, but when this is fixed by a call to ctf_symsect_endianness,
+        init_symtab will be called again with the right endianness in
+        force.  */
       if (ctf_symtab_skippable (&sym))
        {
          *xp = -1u;
       if (ctf_symtab_skippable (&sym))
        {
          *xp = -1u;
@@ -677,7 +683,7 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
 
   unsigned long pop[CTF_K_MAX + 1] = { 0 };
   const ctf_type_t *tp;
 
   unsigned long pop[CTF_K_MAX + 1] = { 0 };
   const ctf_type_t *tp;
-  uint32_t id, dst;
+  uint32_t id;
   uint32_t *xp;
 
   /* We determine whether the dict is a child or a parent based on the value of
   uint32_t *xp;
 
   /* We determine whether the dict is a child or a parent based on the value of
@@ -750,7 +756,8 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
     return ENOMEM;
 
   if ((fp->ctf_names.ctn_readonly
     return ENOMEM;
 
   if ((fp->ctf_names.ctn_readonly
-       = ctf_hash_create (pop[CTF_K_INTEGER] +
+       = ctf_hash_create (pop[CTF_K_UNKNOWN] +
+                         pop[CTF_K_INTEGER] +
                          pop[CTF_K_FLOAT] +
                          pop[CTF_K_FUNCTION] +
                          pop[CTF_K_TYPEDEF] +
                          pop[CTF_K_FLOAT] +
                          pop[CTF_K_FUNCTION] +
                          pop[CTF_K_TYPEDEF] +
@@ -794,6 +801,7 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
 
       switch (kind)
        {
 
       switch (kind)
        {
+       case CTF_K_UNKNOWN:
        case CTF_K_INTEGER:
        case CTF_K_FLOAT:
          /* Names are reused by bit-fields, which are differentiated by their
        case CTF_K_INTEGER:
        case CTF_K_FLOAT:
          /* Names are reused by bit-fields, which are differentiated by their
@@ -947,25 +955,6 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
   ctf_dprintf ("%u base type names hashed\n",
               ctf_hash_size (fp->ctf_names.ctn_readonly));
 
   ctf_dprintf ("%u base type names hashed\n",
               ctf_hash_size (fp->ctf_names.ctn_readonly));
 
-  /* Make an additional pass through the pointer table to find pointers that
-     point to anonymous typedef nodes.  If we find one, modify the pointer table
-     so that the pointer is also known to point to the node that is referenced
-     by the anonymous typedef node.  */
-
-  for (id = 1; id <= fp->ctf_typemax; id++)
-    {
-      if ((dst = fp->ctf_ptrtab[id]) != 0)
-       {
-         tp = LCTF_INDEX_TO_TYPEPTR (fp, id);
-
-         if (LCTF_INFO_KIND (fp, tp->ctt_info) == CTF_K_TYPEDEF
-             && strcmp (ctf_strptr (fp, tp->ctt_name), "") == 0
-             && LCTF_TYPE_ISCHILD (fp, tp->ctt_type) == child
-             && LCTF_TYPE_TO_INDEX (fp, tp->ctt_type) <= fp->ctf_typemax)
-             fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX (fp, tp->ctt_type)] = dst;
-       }
-    }
-
   return 0;
 }
 
   return 0;
 }
 
@@ -974,32 +963,10 @@ init_types (ctf_dict_t *fp, ctf_header_t *cth)
    We flip everything, mindlessly, even 1-byte entities, so that future
    expansions do not require changes to this code.  */
 
    We flip everything, mindlessly, even 1-byte entities, so that future
    expansions do not require changes to this code.  */
 
-/* < C11? define away static assertions.  */
-
-#if !defined (__STDC_VERSION__) || __STDC_VERSION__ < 201112L
-#define _Static_assert(cond, err)
-#endif
-
-/* Swap the endianness of something.  */
-
-#define swap_thing(x)                                                  \
-  do {                                                                 \
-    _Static_assert (sizeof (x) == 1 || (sizeof (x) % 2 == 0            \
-                                       && sizeof (x) <= 8),            \
-                   "Invalid size, update endianness code");            \
-    switch (sizeof (x)) {                                              \
-    case 2: x = bswap_16 (x); break;                                   \
-    case 4: x = bswap_32 (x); break;                                   \
-    case 8: x = bswap_64 (x); break;                                   \
-    case 1: /* Nothing needs doing */                                  \
-      break;                                                           \
-    }                                                                  \
-  } while (0);
-
 /* Flip the endianness of the CTF header.  */
 
 /* Flip the endianness of the CTF header.  */
 
-static void
-flip_header (ctf_header_t *cth)
+void
+ctf_flip_header (ctf_header_t *cth)
 {
   swap_thing (cth->cth_preamble.ctp_magic);
   swap_thing (cth->cth_preamble.ctp_version);
 {
   swap_thing (cth->cth_preamble.ctp_magic);
   swap_thing (cth->cth_preamble.ctp_version);
@@ -1064,26 +1031,48 @@ flip_vars (void *start, size_t len)
    ctf_stype followed by variable data.  */
 
 static int
    ctf_stype followed by variable data.  */
 
 static int
-flip_types (ctf_dict_t *fp, void *start, size_t len)
+flip_types (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)
     {
 {
   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);
 
       swap_thing (t->ctt_name);
       swap_thing (t->ctt_info);
       swap_thing (t->ctt_size);
 
-      uint32_t kind = CTF_V2_INFO_KIND (t->ctt_info);
-      size_t size = t->ctt_size;
-      uint32_t vlen = CTF_V2_INFO_VLEN (t->ctt_info);
-      size_t vbytes = get_vbytes_v2 (fp, kind, size, vlen);
+      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 (_libctf_unlikely_ (size == CTF_LSIZE_SENT))
        {
+         if (to_foreign)
+           size = CTF_TYPE_LSIZE (t);
+
          swap_thing (t->ctt_lsizehi);
          swap_thing (t->ctt_lsizelo);
          swap_thing (t->ctt_lsizehi);
          swap_thing (t->ctt_lsizelo);
-         size = CTF_TYPE_LSIZE (t);
+
+         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_type_t));
        }
       else
@@ -1215,22 +1204,27 @@ flip_types (ctf_dict_t *fp, void *start, size_t len)
 }
 
 /* Flip the endianness of BUF, given the offsets in the (already endian-
 }
 
 /* Flip the endianness of BUF, given the offsets in the (already endian-
-   converted) CTH.
+   converted) CTH.  If TO_FOREIGN is set, flip to foreign-endianness; if not,
+   flip away.
 
    All of this stuff happens before the header is fully initialized, so the
    LCTF_*() macros cannot be used yet.  Since we do not try to endian-convert v1
    data, this is no real loss.  */
 
 
    All of this stuff happens before the header is fully initialized, so the
    LCTF_*() macros cannot be used yet.  Since we do not try to endian-convert v1
    data, this is no real loss.  */
 
-static int
-flip_ctf (ctf_dict_t *fp, ctf_header_t *cth, unsigned char *buf)
+int
+ctf_flip (ctf_dict_t *fp, ctf_header_t *cth, unsigned char *buf,
+         int to_foreign)
 {
 {
+  ctf_dprintf("flipping endianness\n");
+
   flip_lbls (buf + cth->cth_lbloff, cth->cth_objtoff - cth->cth_lbloff);
   flip_objts (buf + cth->cth_objtoff, cth->cth_funcoff - cth->cth_objtoff);
   flip_objts (buf + cth->cth_funcoff, cth->cth_objtidxoff - cth->cth_funcoff);
   flip_objts (buf + cth->cth_objtidxoff, cth->cth_funcidxoff - cth->cth_objtidxoff);
   flip_objts (buf + cth->cth_funcidxoff, cth->cth_varoff - cth->cth_funcidxoff);
   flip_vars (buf + cth->cth_varoff, cth->cth_typeoff - cth->cth_varoff);
   flip_lbls (buf + cth->cth_lbloff, cth->cth_objtoff - cth->cth_lbloff);
   flip_objts (buf + cth->cth_objtoff, cth->cth_funcoff - cth->cth_objtoff);
   flip_objts (buf + cth->cth_funcoff, cth->cth_objtidxoff - cth->cth_funcoff);
   flip_objts (buf + cth->cth_objtidxoff, cth->cth_funcidxoff - cth->cth_objtidxoff);
   flip_objts (buf + cth->cth_funcidxoff, cth->cth_varoff - cth->cth_funcidxoff);
   flip_vars (buf + cth->cth_varoff, cth->cth_typeoff - cth->cth_varoff);
-  return flip_types (fp, buf + cth->cth_typeoff, cth->cth_stroff - cth->cth_typeoff);
+  return flip_types (fp, buf + cth->cth_typeoff,
+                    cth->cth_stroff - cth->cth_typeoff, to_foreign);
 }
 
 /* Set up the ctl hashes in a ctf_dict_t.  Called by both writable and
 }
 
 /* Set up the ctl hashes in a ctf_dict_t.  Called by both writable and
@@ -1437,7 +1431,7 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
     upgrade_header (hp);
 
   if (foreign_endian)
     upgrade_header (hp);
 
   if (foreign_endian)
-    flip_header (hp);
+    ctf_flip_header (hp);
   fp->ctf_openflags = hp->cth_flags;
   fp->ctf_size = hp->cth_stroff + hp->cth_strlen;
 
   fp->ctf_openflags = hp->cth_flags;
   fp->ctf_size = hp->cth_stroff + hp->cth_strlen;
 
@@ -1482,7 +1476,7 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
        != hp->cth_funcoff - hp->cth_objtoff))
     {
       ctf_err_warn (NULL, 0, ECTF_CORRUPT,
        != hp->cth_funcoff - hp->cth_objtoff))
     {
       ctf_err_warn (NULL, 0, ECTF_CORRUPT,
-                   _("Object index section exists is neither empty nor the "
+                   _("Object index section is neither empty nor the "
                      "same length as the object section: %u versus %u "
                      "bytes"), hp->cth_funcoff - hp->cth_objtoff,
                    hp->cth_funcidxoff - hp->cth_objtidxoff);
                      "same length as the object section: %u versus %u "
                      "bytes"), hp->cth_funcoff - hp->cth_objtoff,
                    hp->cth_funcidxoff - hp->cth_objtidxoff);
@@ -1491,10 +1485,11 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
 
   if ((hp->cth_varoff - hp->cth_funcidxoff != 0) &&
       (hp->cth_varoff - hp->cth_funcidxoff
 
   if ((hp->cth_varoff - hp->cth_funcidxoff != 0) &&
       (hp->cth_varoff - hp->cth_funcidxoff
-       != hp->cth_objtidxoff - hp->cth_funcoff))
+       != hp->cth_objtidxoff - hp->cth_funcoff) &&
+      (hp->cth_flags & CTF_F_NEWFUNCINFO))
     {
       ctf_err_warn (NULL, 0, ECTF_CORRUPT,
     {
       ctf_err_warn (NULL, 0, ECTF_CORRUPT,
-                   _("Function index section exists is neither empty nor the "
+                   _("Function index section is neither empty nor the "
                      "same length as the function section: %u versus %u "
                      "bytes"), hp->cth_objtidxoff - hp->cth_funcoff,
                    hp->cth_varoff - hp->cth_funcidxoff);
                      "same length as the function section: %u versus %u "
                      "bytes"), hp->cth_objtidxoff - hp->cth_funcoff,
                    hp->cth_varoff - hp->cth_funcidxoff);
@@ -1549,26 +1544,39 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
          goto bad;
        }
     }
          goto bad;
        }
     }
-  else if (foreign_endian)
+  else
     {
     {
-      if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL)
+      if (_libctf_unlikely_ (ctfsect->cts_size < hdrsz + fp->ctf_size))
        {
        {
-         err = ECTF_ZALLOC;
+         ctf_err_warn (NULL, 0, ECTF_CORRUPT,
+                       _("%lu byte long CTF dictionary overruns %lu byte long CTF section"),
+                       (unsigned long) ctfsect->cts_size,
+                       (unsigned long) (hdrsz + fp->ctf_size));
+         err = ECTF_CORRUPT;
          goto bad;
        }
          goto bad;
        }
-      fp->ctf_dynbase = fp->ctf_base;
-      memcpy (fp->ctf_base, ((unsigned char *) ctfsect->cts_data) + hdrsz,
-             fp->ctf_size);
-      fp->ctf_buf = fp->ctf_base;
-    }
-  else
-    {
-      /* We are just using the section passed in -- but its header may be an old
-        version.  Point ctf_buf past the old header, and never touch it
-        again.  */
-      fp->ctf_base = (unsigned char *) ctfsect->cts_data;
-      fp->ctf_dynbase = NULL;
-      fp->ctf_buf = fp->ctf_base + hdrsz;
+
+      if (foreign_endian)
+       {
+         if ((fp->ctf_base = malloc (fp->ctf_size)) == NULL)
+           {
+             err = ECTF_ZALLOC;
+             goto bad;
+           }
+         fp->ctf_dynbase = fp->ctf_base;
+         memcpy (fp->ctf_base, ((unsigned char *) ctfsect->cts_data) + hdrsz,
+                 fp->ctf_size);
+         fp->ctf_buf = fp->ctf_base;
+       }
+      else
+       {
+         /* We are just using the section passed in -- but its header may
+            be an old version.  Point ctf_buf past the old header, and
+            never touch it again.  */
+         fp->ctf_base = (unsigned char *) ctfsect->cts_data;
+         fp->ctf_dynbase = NULL;
+         fp->ctf_buf = fp->ctf_base + hdrsz;
+       }
     }
 
   /* Once we have uncompressed and validated the CTF data buffer, we can
     }
 
   /* Once we have uncompressed and validated the CTF data buffer, we can
@@ -1580,7 +1588,12 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
      ctf_set_base().  */
 
   ctf_set_version (fp, hp, hp->cth_version);
      ctf_set_base().  */
 
   ctf_set_version (fp, hp, hp->cth_version);
-  ctf_str_create_atoms (fp);
+  if (ctf_str_create_atoms (fp) < 0)
+    {
+      err = ENOMEM;
+      goto bad;
+    }
+
   fp->ctf_parmax = CTF_MAX_PTYPE;
   memcpy (&fp->ctf_data, ctfsect, sizeof (ctf_sect_t));
 
   fp->ctf_parmax = CTF_MAX_PTYPE;
   memcpy (&fp->ctf_data, ctfsect, sizeof (ctf_sect_t));
 
@@ -1624,9 +1637,9 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
   fp->ctf_syn_ext_strtab = syn_strtab;
 
   if (foreign_endian &&
   fp->ctf_syn_ext_strtab = syn_strtab;
 
   if (foreign_endian &&
-      (err = flip_ctf (fp, hp, fp->ctf_buf)) != 0)
+      (err = ctf_flip (fp, hp, fp->ctf_buf, 0)) != 0)
     {
     {
-      /* We can be certain that flip_ctf() will have endian-flipped everything
+      /* We can be certain that ctf_flip() will have endian-flipped everything
         other than the types table when we return.  In particular the header
         is fine, so set it, to allow freeing to use the usual code path.  */
 
         other than the types table when we return.  In particular the header
         is fine, so set it, to allow freeing to use the usual code path.  */
 
@@ -1652,7 +1665,13 @@ ctf_bufopen_internal (const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
      large for the actual size of the object and function info sections: if so,
      ctf_nsyms will be adjusted and the excess will never be used.  It's
      possible to do indexed symbol lookups even without a symbol table, so check
      large for the actual size of the object and function info sections: if so,
      ctf_nsyms will be adjusted and the excess will never be used.  It's
      possible to do indexed symbol lookups even without a symbol table, so check
-     even in that case.  */
+     even in that case.  Initially, we assume the symtab is native-endian: if it
+     isn't, the caller will inform us later by calling ctf_symsect_endianness.  */
+#ifdef WORDS_BIGENDIAN
+  fp->ctf_symsect_little_endian = 0;
+#else
+  fp->ctf_symsect_little_endian = 1;
+#endif
 
   if (symsect != NULL)
     {
 
   if (symsect != NULL)
     {
@@ -1766,6 +1785,7 @@ ctf_dict_close (ctf_dict_t *fp)
     }
   ctf_dynhash_destroy (fp->ctf_dvhash);
 
     }
   ctf_dynhash_destroy (fp->ctf_dvhash);
 
+  ctf_dynhash_destroy (fp->ctf_symhash);
   free (fp->ctf_funcidx_sxlate);
   free (fp->ctf_objtidx_sxlate);
   ctf_dynhash_destroy (fp->ctf_objthash);
   free (fp->ctf_funcidx_sxlate);
   free (fp->ctf_objtidx_sxlate);
   ctf_dynhash_destroy (fp->ctf_objthash);
@@ -1816,6 +1836,7 @@ ctf_dict_close (ctf_dict_t *fp)
   free (fp->ctf_sxlate);
   free (fp->ctf_txlate);
   free (fp->ctf_ptrtab);
   free (fp->ctf_sxlate);
   free (fp->ctf_txlate);
   free (fp->ctf_ptrtab);
+  free (fp->ctf_pptrtab);
 
   free (fp->ctf_header);
   free (fp);
 
   free (fp->ctf_header);
   free (fp);
@@ -1866,6 +1887,22 @@ ctf_getstrsect (const ctf_dict_t *fp)
   return fp->ctf_strtab;
 }
 
   return fp->ctf_strtab;
 }
 
+/* Set the endianness of the symbol table attached to FP.  */
+void
+ctf_symsect_endianness (ctf_dict_t *fp, int little_endian)
+{
+  int old_endianness = fp->ctf_symsect_little_endian;
+
+  fp->ctf_symsect_little_endian = !!little_endian;
+
+  /* If we already have a symtab translation table, we need to repopulate it if
+     our idea of the endianness has changed.  */
+
+  if (old_endianness != fp->ctf_symsect_little_endian
+      && fp->ctf_sxlate != NULL && fp->ctf_symtab.cts_data != NULL)
+    assert (init_symtab (fp, fp->ctf_header, &fp->ctf_symtab) == 0);
+}
+
 /* Return the CTF handle for the parent CTF dict, if one exists.  Otherwise
    return NULL to indicate this dict has no imported parent.  */
 ctf_dict_t *
 /* Return the CTF handle for the parent CTF dict, if one exists.  Otherwise
    return NULL to indicate this dict has no imported parent.  */
 ctf_dict_t *
@@ -1925,7 +1962,8 @@ ctf_cuname_set (ctf_dict_t *fp, const char *name)
 
 /* Import the types from the specified parent dict by storing a pointer to it in
    ctf_parent and incrementing its reference count.  Only one parent is allowed:
 
 /* Import the types from the specified parent dict by storing a pointer to it in
    ctf_parent and incrementing its reference count.  Only one parent is allowed:
-   if a parent already exists, it is replaced by the new parent.  */
+   if a parent already exists, it is replaced by the new parent.  The pptrtab
+   is wiped, and will be refreshed by the next ctf_lookup_by_name call.  */
 int
 ctf_import (ctf_dict_t *fp, ctf_dict_t *pfp)
 {
 int
 ctf_import (ctf_dict_t *fp, ctf_dict_t *pfp)
 {
@@ -1939,6 +1977,11 @@ ctf_import (ctf_dict_t *fp, ctf_dict_t *pfp)
     ctf_dict_close (fp->ctf_parent);
   fp->ctf_parent = NULL;
 
     ctf_dict_close (fp->ctf_parent);
   fp->ctf_parent = NULL;
 
+  free (fp->ctf_pptrtab);
+  fp->ctf_pptrtab = NULL;
+  fp->ctf_pptrtab_len = 0;
+  fp->ctf_pptrtab_typemax = 0;
+
   if (pfp != NULL)
     {
       int err;
   if (pfp != NULL)
     {
       int err;
@@ -1973,6 +2016,10 @@ ctf_import_unref (ctf_dict_t *fp, ctf_dict_t *pfp)
     ctf_dict_close (fp->ctf_parent);
   fp->ctf_parent = NULL;
 
     ctf_dict_close (fp->ctf_parent);
   fp->ctf_parent = NULL;
 
+  free (fp->ctf_pptrtab);
+  fp->ctf_pptrtab = NULL;
+  fp->ctf_pptrtab_len = 0;
+  fp->ctf_pptrtab_typemax = 0;
   if (pfp != NULL)
     {
       int err;
   if (pfp != NULL)
     {
       int err;
This page took 0.041544 seconds and 4 git commands to generate.