From: Alan Modra Date: Thu, 6 Apr 2023 00:01:08 +0000 (+0930) Subject: objdump print_debugging_info memory leaks X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a5f3ca48236a79b0cf78a82dee1cc0241a975eb7;p=binutils-gdb.git 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. --- diff --git a/binutils/prdbg.c b/binutils/prdbg.c index cf39e9db39a..fb351476893 100644 --- a/binutils/prdbg.c +++ b/binutils/prdbg.c @@ -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;