objdump print_debugging_info memory leaks
authorAlan Modra <amodra@gmail.com>
Thu, 6 Apr 2023 00:01:08 +0000 (09:31 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 6 Apr 2023 00:22:17 +0000 (09:52 +0930)
Fix memory leaks and do a general tidy of the code for printing coff
and stabs debug.

* prdbg.c: Delete unnneeded forward function declarations.
Delete unnecessary casts throughout.  Free all strings
returned from pop_type throughout file.
(struct pr_stack): Delete "num_parents".  Replace tests for
"num_parents" non-zero with tests of "parents" non-NULL
throughout.  Free "parents" before assigning, and set to NULL
after freeing.  Remove const from "method".  Always strdup
strings assigned to method, and free before assigning.
(print_debugging_info): Free info.stack and info.filename.

binutils/prdbg.c

index cf39e9db39a7dad9d973420d1f159c365a92a2fc..fb351476893c2c42d9289259237f7450bfab10e7 100644 (file)
@@ -65,25 +65,14 @@ struct pr_stack
   /* Current visibility of fields if this is a class.  */
   enum debug_visibility visibility;
   /* Name of the current method we are handling.  */
-  const char *method;
+  char *method;
   /* The following are used only by the tags code (tg_).  */
   /* Type for the container (struct, union, class, union class).  */
   const char *flavor;
   /* A comma separated list of parent classes.  */
   char *parents;
-  /* How many parents contains parents.  */
-  int num_parents;
 };
 
-static void indent (struct pr_handle *);
-static bool push_type (struct pr_handle *, const char *);
-static bool prepend_type (struct pr_handle *, const char *);
-static bool append_type (struct pr_handle *, const char *);
-static bool substitute_type (struct pr_handle *, const char *);
-static bool indent_type (struct pr_handle *);
-static char *pop_type (struct pr_handle *);
-static void print_vma (bfd_vma, char *, bool, bool);
-static bool pr_fix_visibility (struct pr_handle *, enum debug_visibility);
 static bool pr_start_compilation_unit (void *, const char *);
 static bool pr_start_source (void *, const char *);
 static bool pr_empty_type (void *);
@@ -138,13 +127,9 @@ static bool pr_start_block (void *, bfd_vma);
 static bool pr_end_block (void *, bfd_vma);
 static bool pr_end_function (void *);
 static bool pr_lineno (void *, const char *, unsigned long, bfd_vma);
-static bool append_parent (struct pr_handle *, const char *);
-/* Only used by tg_ code.  */
-static bool tg_fix_visibility
-  (struct pr_handle *, enum debug_visibility);
-static void find_address_in_section (bfd *, asection *, void *);
-static void translate_addresses (bfd *, char *, FILE *, asymbol **);
+
 static const char *visibility_name (enum debug_visibility);
+
 /* Tags style replacements.  */
 static bool tg_start_compilation_unit (void *, const char *);
 static bool tg_start_source (void *, const char *);
@@ -308,8 +293,18 @@ print_debugging_info (FILE *f, void *dhandle, bfd *abfd, asymbol **syms,
       fputs ("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n", f);
     }
 
-  return as_tags ? debug_write (dhandle, &tg_fns, (void *) & info)
-    : debug_write (dhandle, &pr_fns, (void *) & info);
+  bool ret = debug_write (dhandle, as_tags ? &tg_fns : &pr_fns, &info);
+  while (info.stack != NULL)
+    {
+      struct pr_stack *s = info.stack;
+      info.stack = s->next;
+      free (s->type);
+      free (s->method);
+      free (s->parents);
+      free (s);
+    }
+  free (info.filename);
+  return ret;
 }
 \f
 /* Indent to the current indentation level.  */
@@ -333,7 +328,7 @@ push_type (struct pr_handle *info, const char *type)
   if (type == NULL)
     return false;
 
-  n = (struct pr_stack *) xmalloc (sizeof *n);
+  n = xmalloc (sizeof *n);
   memset (n, 0, sizeof *n);
 
   n->type = xstrdup (type);
@@ -354,7 +349,7 @@ prepend_type (struct pr_handle *info, const char *s)
 
   assert (info->stack != NULL);
 
-  n = (char *) xmalloc (strlen (s) + strlen (info->stack->type) + 1);
+  n = xmalloc (strlen (s) + strlen (info->stack->type) + 1);
   sprintf (n, "%s%s", s, info->stack->type);
   free (info->stack->type);
   info->stack->type = n;
@@ -375,8 +370,7 @@ append_type (struct pr_handle *info, const char *s)
   assert (info->stack != NULL);
 
   len = strlen (info->stack->type);
-  info->stack->type = (char *) xrealloc (info->stack->type,
-                                        len + strlen (s) + 1);
+  info->stack->type = xrealloc (info->stack->type, len + strlen (s) + 1);
   strcpy (info->stack->type + len, s);
 
   return true;
@@ -395,8 +389,7 @@ append_parent (struct pr_handle *info, const char *s)
   assert (info->stack != NULL);
 
   len = info->stack->parents ? strlen (info->stack->parents) : 0;
-  info->stack->parents = (char *) xrealloc (info->stack->parents,
-                                           len + strlen (s) + 1);
+  info->stack->parents = xrealloc (info->stack->parents, len + strlen (s) + 1);
   strcpy (info->stack->parents + len, s);
 
   return true;
@@ -418,7 +411,7 @@ substitute_type (struct pr_handle *info, const char *s)
     {
       char *n;
 
-      n = (char *) xmalloc (strlen (info->stack->type) + strlen (s));
+      n = xmalloc (strlen (info->stack->type) + strlen (s));
 
       memcpy (n, info->stack->type, u - info->stack->type);
       strcpy (n + (u - info->stack->type), s);
@@ -693,17 +686,14 @@ pr_function_type (void *p, int argcount, bool varargs)
     {
       int i;
 
-      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+      arg_types = xmalloc (argcount * sizeof (*arg_types));
       for (i = argcount - 1; i >= 0; i--)
        {
-         if (! substitute_type (info, ""))
-           {
-             free (arg_types);
-             return false;
-           }
-         arg_types[i] = pop_type (info);
-         if (arg_types[i] == NULL)
+         if (!substitute_type (info, "")
+             || (arg_types[i] = pop_type (info)) == NULL)
            {
+             for (int j = i + 1; j < argcount; j++)
+               free (arg_types[j]);
              free (arg_types);
              return false;
            }
@@ -715,7 +705,7 @@ pr_function_type (void *p, int argcount, bool varargs)
 
   /* Now the return type is on the top of the stack.  */
 
-  s = (char *) xmalloc (len);
+  s = xmalloc (len);
   strcpy (s, "(|) (");
 
   if (argcount < 0)
@@ -729,6 +719,7 @@ pr_function_type (void *p, int argcount, bool varargs)
          if (i > 0)
            strcat (s, ", ");
          strcat (s, arg_types[i]);
+         free (arg_types[i]);
        }
       if (varargs)
        {
@@ -736,8 +727,7 @@ pr_function_type (void *p, int argcount, bool varargs)
            strcat (s, ", ");
          strcat (s, "...");
        }
-      if (argcount > 0)
-       free (arg_types);
+      free (arg_types);
     }
 
   strcat (s, ")");
@@ -814,22 +804,27 @@ pr_array_type (void *p, bfd_signed_vma lower, bfd_signed_vma upper,
     }
 
   if (! substitute_type (info, ab))
-    return false;
+    goto fail;
 
   if (strcmp (range_type, "int") != 0)
     {
       if (! append_type (info, ":")
          || ! append_type (info, range_type))
-       return false;
+       goto fail;
     }
 
   if (stringp)
     {
       if (! append_type (info, " /* string */"))
-       return false;
+       goto fail;
     }
 
+  free (range_type);
   return true;
+
+ fail:
+  free (range_type);
+  return false;
 }
 
 /* Make a set type.  */
@@ -870,10 +865,12 @@ pr_offset_type (void *p)
   if (t == NULL)
     return false;
 
-  return (substitute_type (info, "")
-         && prepend_type (info, " ")
-         && prepend_type (info, t)
-         && append_type (info, "::|"));
+  bool ret = (substitute_type (info, "")
+             && prepend_type (info, " ")
+             && prepend_type (info, t)
+             && append_type (info, "::|"));
+  free (t);
+  return ret;
 }
 
 /* Make a method type.  */
@@ -883,21 +880,20 @@ pr_method_type (void *p, bool domain, int argcount, bool varargs)
 {
   struct pr_handle *info = (struct pr_handle *) p;
   unsigned int len;
-  char *domain_type;
+  char *domain_type = NULL, *free_domain = NULL;
   char **arg_types;
   char *s;
 
   len = 10;
 
-  if (! domain)
-    domain_type = NULL;
-  else
+  if (domain)
     {
       if (! substitute_type (info, ""))
        return false;
       domain_type = pop_type (info);
       if (domain_type == NULL)
        return false;
+      free_domain = domain_type;
       if (startswith (domain_type, "class ")
          && strchr (domain_type + sizeof "class " - 1, ' ') == NULL)
        domain_type += sizeof "class " - 1;
@@ -917,17 +913,14 @@ pr_method_type (void *p, bool domain, int argcount, bool varargs)
     {
       int i;
 
-      arg_types = (char **) xmalloc (argcount * sizeof *arg_types);
+      arg_types = xmalloc (argcount * sizeof (*arg_types));
       for (i = argcount - 1; i >= 0; i--)
        {
-         if (! substitute_type (info, ""))
-           {
-             free (arg_types);
-             return false;
-           }
-         arg_types[i] = pop_type (info);
-         if (arg_types[i] == NULL)
+         if (!substitute_type (info, "")
+             || (arg_types[i] = pop_type (info)) == NULL)
            {
+             for (int j = i + 1; j < argcount; ++j)
+               free (arg_types[j]);
              free (arg_types);
              return false;
            }
@@ -939,11 +932,13 @@ pr_method_type (void *p, bool domain, int argcount, bool varargs)
 
   /* Now the return type is on the top of the stack.  */
 
-  s = (char *) xmalloc (len);
-  if (! domain)
-    *s = '\0';
-  else
-    strcpy (s, domain_type);
+  s = xmalloc (len);
+  *s = 0;
+  if (domain)
+    {
+      strcpy (s, domain_type);
+      free (free_domain);
+    }
   strcat (s, "::| (");
 
   if (argcount < 0)
@@ -957,6 +952,7 @@ pr_method_type (void *p, bool domain, int argcount, bool varargs)
          if (i > 0)
            strcat (s, ", ");
          strcat (s, arg_types[i]);
+         free (arg_types[i]);
        }
       if (varargs)
        {
@@ -964,18 +960,14 @@ pr_method_type (void *p, bool domain, int argcount, bool varargs)
            strcat (s, ", ");
          strcat (s, "...");
        }
-      if (argcount > 0)
-       free (arg_types);
+      free (arg_types);
     }
 
   strcat (s, ")");
 
-  if (! substitute_type (info, s))
-    return false;
-
+  bool ret = substitute_type (info, s);
   free (s);
-
-  return true;
+  return ret;
 }
 
 /* Make a const qualified type.  */
@@ -1143,10 +1135,9 @@ pr_struct_field (void *p, const char *name, bfd_vma bitpos, bfd_vma bitsize,
   if (t == NULL)
     return false;
 
-  if (! pr_fix_visibility (info, visibility))
-    return false;
-
-  return append_type (info, t);
+  bool ret = pr_fix_visibility (info, visibility) && append_type (info, t);
+  free (t);
+  return ret;
 }
 
 /* Finish a struct type.  */
@@ -1181,6 +1172,7 @@ pr_start_class_type (void *p, const char *tag, unsigned int id,
 {
   struct pr_handle *info = (struct pr_handle *) p;
   char *tv = NULL;
+  bool ret = false;
 
   info->indent += 2;
 
@@ -1192,11 +1184,11 @@ pr_start_class_type (void *p, const char *tag, unsigned int id,
     }
 
   if (! push_type (info, structp ? "class " : "union class "))
-    return false;
+    goto out;
   if (tag != NULL)
     {
       if (! append_type (info, tag))
-       return false;
+       goto out;
     }
   else
     {
@@ -1204,15 +1196,15 @@ pr_start_class_type (void *p, const char *tag, unsigned int id,
 
       sprintf (idbuf, "%%anon%u", id);
       if (! append_type (info, idbuf))
-       return false;
+       goto out;
     }
 
   if (! append_type (info, " {"))
-    return false;
+    goto out;
   if (size != 0 || vptr || ownvptr || tag != NULL)
     {
       if (! append_type (info, " /*"))
-       return false;
+       goto out;
 
       if (size != 0)
        {
@@ -1221,23 +1213,23 @@ pr_start_class_type (void *p, const char *tag, unsigned int id,
          sprintf (ab, "%u", size);
          if (! append_type (info, " size ")
              || ! append_type (info, ab))
-           return false;
+           goto out;
        }
 
       if (vptr)
        {
          if (! append_type (info, " vtable "))
-           return false;
+           goto out;
          if (ownvptr)
            {
              if (! append_type (info, "self "))
-               return false;
+               goto out;
            }
          else
            {
              if (! append_type (info, tv)
                  || ! append_type (info, " "))
-               return false;
+               goto out;
            }
        }
 
@@ -1247,17 +1239,19 @@ pr_start_class_type (void *p, const char *tag, unsigned int id,
 
          sprintf (ab, " id %u", id);
          if (! append_type (info, ab))
-           return false;
+           goto out;
        }
 
       if (! append_type (info, " */"))
-       return false;
+       goto out;
     }
 
   info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
 
-  return (append_type (info, "\n")
-         && indent_type (info));
+  ret = append_type (info, "\n") && indent_type (info);
+ out:
+  free (tv);
+  return ret;
 }
 
 /* Add a static member to a class.  */
@@ -1283,10 +1277,9 @@ pr_class_static_member (void *p, const char *name, const char *physname,
   if (t == NULL)
     return false;
 
-  if (! pr_fix_visibility (info, visibility))
-    return false;
-
-  return append_type (info, t);
+  bool ret = pr_fix_visibility (info, visibility) && append_type (info, t);
+  free (t);
+  return ret;
 }
 
 /* Add a base class to a class.  */
@@ -1310,13 +1303,15 @@ pr_class_baseclass (void *p, bfd_vma bitpos, bool is_virtual,
   if (t == NULL)
     return false;
 
-  if (startswith (t, "class "))
-    t += sizeof "class " - 1;
-
   /* Push it back on to take advantage of the prepend_type and
      append_type routines.  */
-  if (! push_type (info, t))
-    return false;
+  if (! push_type (info, t + (startswith (t, "class ")
+                             ? sizeof "class " - 1 : 0)))
+    {
+      free (t);
+      return false;
+    }
+  free (t);
 
   if (is_virtual)
     {
@@ -1372,7 +1367,7 @@ pr_class_baseclass (void *p, bfd_vma bitpos, bool is_virtual,
   if (t == NULL)
     return false;
 
-  n = (char *) xmalloc (strlen (info->stack->type) + strlen (t) + 1);
+  n = xmalloc (strlen (info->stack->type) + strlen (t) + 1);
   memcpy (n, info->stack->type, s - info->stack->type);
   strcpy (n + (s - info->stack->type), t);
   strcat (n, s);
@@ -1393,7 +1388,8 @@ pr_class_start_method (void *p, const char *name)
   struct pr_handle *info = (struct pr_handle *) p;
 
   assert (info->stack != NULL);
-  info->stack->method = name;
+  free (info->stack->method);
+  info->stack->method = xstrdup (name);
   return true;
 }
 
@@ -1408,6 +1404,7 @@ pr_class_method_variant (void *p, const char *physname,
   struct pr_handle *info = (struct pr_handle *) p;
   char *method_type;
   char *context_type;
+  bool ret = false;
 
   assert (info->stack != NULL);
   assert (info->stack->next != NULL);
@@ -1443,19 +1440,19 @@ pr_class_method_variant (void *p, const char *physname,
     {
       context_type = pop_type (info);
       if (context_type == NULL)
-       return false;
+       goto out;
     }
 
   /* Now the top of the stack is the class.  */
 
   if (! pr_fix_visibility (info, visibility))
-    return false;
+    goto out;
 
   if (! append_type (info, method_type)
       || ! append_type (info, " /* ")
       || ! append_type (info, physname)
       || ! append_type (info, " "))
-    return false;
+    goto out;
   if (context || voffset != 0)
     {
       char ab[22];
@@ -1465,16 +1462,19 @@ pr_class_method_variant (void *p, const char *physname,
          if (! append_type (info, "context ")
              || ! append_type (info, context_type)
              || ! append_type (info, " "))
-           return false;
+           goto out;
        }
       print_vma (voffset, ab, true, false);
       if (! append_type (info, "voffset ")
          || ! append_type (info, ab))
-       return false;
+       goto out;
     }
 
-  return (append_type (info, " */;\n")
-         && indent_type (info));
+  ret = append_type (info, " */;\n") && indent_type (info);
+ out:
+  free (method_type);
+  free (context_type);
+  return ret;
 }
 
 /* Add a static variant to a method.  */
@@ -1518,14 +1518,14 @@ pr_class_static_method_variant (void *p, const char *physname,
 
   /* Now the top of the stack is the class.  */
 
-  if (! pr_fix_visibility (info, visibility))
-    return false;
-
-  return (append_type (info, method_type)
-         && append_type (info, " /* ")
-         && append_type (info, physname)
-         && append_type (info, " */;\n")
-         && indent_type (info));
+  bool ret = (pr_fix_visibility (info, visibility)
+             && append_type (info, method_type)
+             && append_type (info, " /* ")
+             && append_type (info, physname)
+             && append_type (info, " */;\n")
+             && indent_type (info));
+  free (method_type);
+  return ret;
 }
 
 /* Finish up a method.  */
@@ -1535,6 +1535,7 @@ pr_class_end_method (void *p)
 {
   struct pr_handle *info = (struct pr_handle *) p;
 
+  free (info->stack->method);
   info->stack->method = NULL;
   return true;
 }
@@ -1761,6 +1762,8 @@ pr_start_function (void *p, const char *name, bool global)
     fprintf (info->f, "static ");
   fprintf (info->f, "%s (", t);
 
+  free (t);
+
   info->parameter = 1;
 
   return true;
@@ -1928,7 +1931,7 @@ tg_start_compilation_unit (void * p, const char *fname ATTRIBUTE_UNUSED)
 
   free (info->filename);
   /* Should it be relative? best way to do it here?.  */
-  info->filename = strdup (fname);
+  info->filename = xstrdup (fname);
 
   return true;
 }
@@ -1942,7 +1945,7 @@ tg_start_source (void *p, const char *fname)
 
   free (info->filename);
   /* Should it be relative? best way to do it here?.  */
-  info->filename = strdup (fname);
+  info->filename = xstrdup (fname);
 
   return true;
 }
@@ -2045,16 +2048,24 @@ tg_struct_field (void *p, const char *name, bfd_vma bitpos ATTRIBUTE_UNUSED,
     return false;
 
   if (! tg_fix_visibility (info, visibility))
-    return false;
+    {
+      free (t);
+      return false;
+    }
 
   /* It happens, a bug? */
   if (! name[0])
-    return true;
+    {
+      free (t);
+      return true;
+    }
 
   fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n",
           name, info->filename, t, info->stack->flavor, info->stack->type,
           visibility_name (visibility));
 
+  free (t);
+
   return true;
 }
 
@@ -2079,6 +2090,7 @@ tg_start_class_type (void *p, const char *tag, unsigned int id,
   char *tv = NULL;
   const char *name;
   char idbuf[20];
+  bool ret = false;
 
   info->indent += 2;
 
@@ -2098,35 +2110,38 @@ tg_start_class_type (void *p, const char *tag, unsigned int id,
     }
 
   if (! push_type (info, name))
-    return false;
+    goto out;
 
   info->stack->flavor = structp ? "class" : "union class";
+  free (info->stack->parents);
   info->stack->parents = NULL;
-  info->stack->num_parents = 0;
 
   if (size != 0 || vptr || ownvptr || tag != NULL)
     {
       if (vptr)
        {
          if (! append_type (info, " vtable "))
-           return false;
+           goto out;
          if (ownvptr)
            {
              if (! append_type (info, "self "))
-               return false;
+               goto out;
            }
          else
            {
              if (! append_type (info, tv)
                  || ! append_type (info, " "))
-               return false;
+               goto out;
            }
        }
     }
 
   info->stack->visibility = DEBUG_VISIBILITY_PRIVATE;
 
-  return true;
+  ret = true;
+ out:
+  free (tv);
+  return ret;
 }
 
 /* Add a static member to a class.  */
@@ -2143,9 +2158,7 @@ tg_class_static_member (void *p, const char *name,
 
   len_var = strlen (name);
   len_class = strlen (info->stack->next->type);
-  full_name = (char *) xmalloc (len_var + len_class + 3);
-  if (! full_name)
-    return false;
+  full_name = xmalloc (len_var + len_class + 3);
   sprintf (full_name, "%s::%s", info->stack->next->type, name);
 
   if (! substitute_type (info, full_name))
@@ -2199,13 +2212,15 @@ tg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED,
   if (t == NULL)
     return false;
 
-  if (startswith (t, "class "))
-    t += sizeof "class " - 1;
-
   /* Push it back on to take advantage of the prepend_type and
      append_type routines.  */
-  if (! push_type (info, t))
-    return false;
+  if (! push_type (info, t + (startswith (t, "class ")
+                             ? sizeof "class " - 1 : 0)))
+    {
+      free (t);
+      return false;
+    }
+  free (t);
 
   if (is_virtual)
     {
@@ -2236,16 +2251,10 @@ tg_class_baseclass (void *p, bfd_vma bitpos ATTRIBUTE_UNUSED,
   if (t == NULL)
     return false;
 
-  if (info->stack->num_parents && ! append_parent (info, ", "))
-    return false;
-
-  if (! append_parent (info, t))
-    return false;
-  info->stack->num_parents++;
-
+  bool ret = ((!info->stack->parents || append_parent (info, ", "))
+             && append_parent (info, t));
   free (t);
-
-  return true;
+  return ret;
 }
 
 /* Add a variant to a method.  */
@@ -2401,10 +2410,11 @@ tg_end_class_type (void *p)
 
   fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type,
           info->filename, info->stack->flavor);
-  if (info->stack->num_parents)
+  if (info->stack->parents)
     {
       fprintf  (info->f, "\tinherits:%s", info->stack->parents);
       free (info->stack->parents);
+      info->stack->parents = NULL;
     }
   fputc ('\n', info->f);
 
@@ -2628,6 +2638,7 @@ tg_start_function (void *p, const char *name, bool global)
   if (! substitute_type (info, dname ? dname : name))
     return false;
 
+  free (info->stack->method);
   info->stack->method = NULL;
   if (dname != NULL)
     {
@@ -2636,12 +2647,13 @@ tg_start_function (void *p, const char *name, bool global)
       if (sep)
        {
          info->stack->method = dname;
+         dname = NULL;
          *sep = 0;
          name = sep + 2;
        }
       else
        {
-         info->stack->method = "";
+         info->stack->method = xstrdup ("");
          name = dname;
        }
       sep = strchr (name, '(');
@@ -2650,7 +2662,9 @@ tg_start_function (void *p, const char *name, bool global)
       /* Obscure functions as type_info function.  */
     }
 
+  free (info->stack->parents);
   info->stack->parents = strdup (name);
+  free (dname);
 
   if (! info->stack->method && ! append_type (info, "("))
     return false;
@@ -2686,14 +2700,23 @@ tg_function_parameter (void *p, const char *name, enum debug_parm_kind kind,
   if (! info->stack->method)
     {
       if (info->parameter != 1 && ! append_type (info, ", "))
-       return false;
+       {
+         free (t);
+         return false;
+       }
 
       if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG)
        if (! append_type (info, "register "))
-         return false;
+         {
+           free (t);
+           return false;
+         }
 
       if (! append_type (info, t))
-       return false;
+       {
+         free (t);
+         return false;
+       }
     }
 
   free (t);
@@ -2720,6 +2743,7 @@ tg_start_block (void *p, bfd_vma addr)
       /* Delayed name.  */
       fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename);
       free (info->stack->parents);
+      info->stack->parents = NULL;
 
       print_vma (addr, ab, true, true);
       translate_addresses (info->abfd, ab, info->f, info->syms);
@@ -2740,14 +2764,14 @@ tg_start_block (void *p, bfd_vma addr)
       if (t == NULL)
        return false;
       fprintf (info->f, ";\"\tkind:%c\ttype:%s", kind, t);
+      free (t);
       if (local)
        fputs ("\tfile:", info->f);
       if (partof)
-       {
-         fprintf (info->f, "\tclass:%s", partof);
-         free (partof);
-       }
+       fprintf (info->f, "\tclass:%s", partof);
       fputc ('\n', info->f);
+      free (info->stack->method);
+      info->stack->method = NULL;
     }
 
   return true;