objdump print_debugging_info memory leaks

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.
This commit is contained in:
Alan Modra 2023-04-06 09:31:08 +09:30
parent ff93c7b1a2
commit a5f3ca4823

View 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;
}
/* 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;