/* stabs.c -- Parse stabs debugging information
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GNU Binutils.
static bfd_boolean
parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
- int desc, bfd_vma value, const char *string)
+ int desc ATTRIBUTE_UNUSED, bfd_vma value, const char *string)
{
const char *p;
char *name;
debug_type dtype;
bfd_boolean synonym;
bfd_boolean self_crossref;
- unsigned int lineno;
debug_type *slot;
p = strchr (string, ':');
}
}
- /* GCC 2.x puts the line number in desc. SunOS apparently puts in
- the number of bytes occupied by a type or object, which we
- ignore. */
- if (info->gcc_compiled >= 2)
- lineno = desc;
- else
- lineno = 0;
-
/* FIXME: Sometimes the special C++ names start with '.'. */
name = NULL;
if (string[0] == '$')
store the slot used if the type is being defined. */
static debug_type
-parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, debug_type **slotp)
+parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name, const char **pp, debug_type **slotp)
{
const char *orig;
int typenums[2];
fleep:T20=xsfleep:
which define structures in terms of themselves. We need to
tell the caller to avoid building a circular structure. */
- if (typename != NULL
- && strncmp (typename, *pp, p - *pp) == 0
- && typename[p - *pp] == '\0')
+ if (type_name != NULL
+ && strncmp (type_name, *pp, p - *pp) == 0
+ && type_name[p - *pp] == '\0')
info->self_crossref = TRUE;
dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
case 'r':
/* Range type. */
- dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums);
+ dtype = parse_stab_range_type (dhandle, info, type_name, pp, typenums);
break;
case 'b':
case 's':
case 'u':
/* Struct or union type. */
- dtype = parse_stab_struct_type (dhandle, info, typename, pp,
+ dtype = parse_stab_struct_type (dhandle, info, type_name, pp,
descriptor == 's', typenums);
break;
/* Parse a range type. */
static debug_type
-parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, const int *typenums)
+parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type_name, const char **pp, const int *typenums)
{
const char *orig;
int rangenums[2];
long long int:t6=r1;0;-1;
long long unsigned int:t7=r1;0;-1;
We hack here to handle this reasonably. */
- if (typename != NULL)
+ if (type_name != NULL)
{
- if (strcmp (typename, "long long int") == 0)
+ if (strcmp (type_name, "long long int") == 0)
return debug_make_int_type (dhandle, 8, FALSE);
- else if (strcmp (typename, "long long unsigned int") == 0)
+ else if (strcmp (type_name, "long long unsigned int") == 0)
return debug_make_int_type (dhandle, 8, TRUE);
}
/* FIXME: The size here really depends upon the target. */
if (**pp != ',')
{
bad_stab (orig);
+ free (name);
+ free (names);
+ free (values);
return DEBUG_TYPE_NULL;
}
++*pp;
const char *tagname, const char **pp,
bfd_boolean structp, const int *typenums)
{
- const char *orig;
bfd_vma size;
debug_baseclass *baseclasses;
- debug_field *fields;
+ debug_field *fields = NULL;
bfd_boolean statics;
debug_method *methods;
debug_type vptrbase;
bfd_boolean ownvptr;
- orig = *pp;
-
/* Get the size. */
size = parse_number (pp, (bfd_boolean *) NULL);
|| ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
|| ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
&ownvptr))
- return DEBUG_TYPE_NULL;
+ {
+ if (fields != NULL)
+ free (fields);
+ return DEBUG_TYPE_NULL;
+ }
if (! statics
&& baseclasses == NULL
for (i = 0; i < c; i++)
{
- bfd_boolean virtual;
+ bfd_boolean is_virtual;
enum debug_visibility visibility;
bfd_vma bitpos;
debug_type type;
switch (**pp)
{
case '0':
- virtual = FALSE;
+ is_virtual = FALSE;
break;
case '1':
- virtual = TRUE;
+ is_virtual = TRUE;
break;
default:
warn_stab (orig, _("unknown virtual character for baseclass"));
- virtual = FALSE;
+ is_virtual = FALSE;
break;
}
++*pp;
if (type == DEBUG_TYPE_NULL)
return FALSE;
- classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
+ classes[i] = debug_make_baseclass (dhandle, type, bitpos, is_virtual,
visibility);
if (classes[i] == DEBUG_BASECLASS_NULL)
return FALSE;
{
++*pp;
if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
- return FALSE;
+ {
+ free (fields);
+ return FALSE;
+ }
++c;
continue;
}
if (p == NULL)
{
bad_stab (orig);
+ free (fields);
return FALSE;
}
int cpp_abbrev;
debug_type context;
const char *name;
- const char *typename;
+ const char *type_name;
debug_type type;
bfd_vma bitpos;
break;
case 'b':
/* $vb -- a virtual bsomethingorother */
- typename = debug_get_type_name (dhandle, context);
- if (typename == NULL)
+ type_name = debug_get_type_name (dhandle, context);
+ if (type_name == NULL)
{
warn_stab (orig, _("unnamed $vb type"));
- typename = "FOO";
+ type_name = "FOO";
}
- name = concat ("_vb$", typename, (const char *) NULL);
+ name = concat ("_vb$", type_name, (const char *) NULL);
break;
default:
warn_stab (orig, _("unrecognized C++ abbreviation"));
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
- return FALSE;
+ {
+ free (name);
+ return FALSE;
+ }
if (**pp == ':')
{
if (p == NULL)
{
bad_stab (orig);
+ free (name);
return FALSE;
}
if (**pp != ',')
{
bad_stab (orig);
+ free (name);
return FALSE;
}
++*pp;
if (**pp != ',')
{
bad_stab (orig);
+ free (name);
return FALSE;
}
++*pp;
if (**pp != ';')
{
bad_stab (orig);
+ free (name);
return FALSE;
}
++*pp;
debug_method *methods;
unsigned int c;
unsigned int alloc;
+ char *name = NULL;
+ debug_method_variant *variants = NULL;
+ char *argtypes = NULL;
*retp = NULL;
while (**pp != ';')
{
const char *p;
- char *name;
- debug_method_variant *variants;
unsigned int cvars;
unsigned int allocvars;
debug_type look_ahead_type;
if (*p != '.')
{
bad_stab (orig);
- return FALSE;
+ goto fail;
}
name = savestring (*pp, p - *pp);
*pp = p + 1;
{
debug_type type;
bfd_boolean stub;
- char *argtypes;
enum debug_visibility visibility;
bfd_boolean constp, volatilep, staticp;
bfd_vma voffset;
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
- return FALSE;
+ goto fail;
+
if (**pp != ':')
{
bad_stab (orig);
- return FALSE;
+ goto fail;
}
}
if (p == NULL)
{
bad_stab (orig);
- return FALSE;
+ goto fail;
}
stub = FALSE;
if (**pp != ';')
{
bad_stab (orig);
- return FALSE;
+ goto fail;
}
++*pp;
voffset &= 0x7fffffff;
if (**pp != ';')
{
bad_stab (orig);
- return FALSE;
+ goto fail;
}
++*pp;
}
argtypes string is the mangled form of the argument
types, and the full type and the physical name must be
extracted from them. */
- if (! stub)
- physname = argtypes;
- else
+ physname = argtypes;
+ if (stub)
{
debug_type class_type, return_type;
class_type = stab_find_type (dhandle, info, typenums);
if (class_type == DEBUG_TYPE_NULL)
- return FALSE;
+ goto fail;
return_type = debug_get_return_type (dhandle, type);
if (return_type == DEBUG_TYPE_NULL)
{
bad_stab (orig);
- return FALSE;
+ goto fail;
}
type = parse_stab_argtypes (dhandle, info, class_type, name,
tagname, return_type, argtypes,
constp, volatilep, &physname);
if (type == DEBUG_TYPE_NULL)
- return FALSE;
+ goto fail;
}
if (cvars + 1 >= allocvars)
constp,
volatilep);
if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
- return FALSE;
+ goto fail;
++cvars;
}
*retp = methods;
return TRUE;
+
+ fail:
+ if (name != NULL)
+ free (name);
+ if (variants != NULL)
+ free (variants);
+ if (argtypes != NULL)
+ free (argtypes);
+ return FALSE;
}
/* Parse a string representing argument types for a method. Stabs
|| CONST_STRNEQ (argtypes, "__dt"));
is_v3 = argtypes[0] == '_' && argtypes[1] == 'Z';
- if (is_destructor || is_full_physname_constructor || is_v3)
- *pphysname = argtypes;
- else
+ if (!(is_destructor || is_full_physname_constructor || is_v3))
{
unsigned int len;
const char *const_prefix;
stab_find_slot (struct stab_handle *info, const int *typenums)
{
int filenum;
- int index;
+ int tindex;
struct stab_types **ps;
filenum = typenums[0];
- index = typenums[1];
+ tindex = typenums[1];
if (filenum < 0 || (unsigned int) filenum >= info->files)
{
fprintf (stderr, _("Type file number %d out of range\n"), filenum);
return NULL;
}
- if (index < 0)
+ if (tindex < 0)
{
- fprintf (stderr, _("Type index number %d out of range\n"), index);
+ fprintf (stderr, _("Type index number %d out of range\n"), tindex);
return NULL;
}
ps = info->file_types + filenum;
- while (index >= STAB_TYPES_SLOTS)
+ while (tindex >= STAB_TYPES_SLOTS)
{
if (*ps == NULL)
{
memset (*ps, 0, sizeof **ps);
}
ps = &(*ps)->next;
- index -= STAB_TYPES_SLOTS;
+ tindex -= STAB_TYPES_SLOTS;
}
if (*ps == NULL)
{
memset (*ps, 0, sizeof **ps);
}
- return (*ps)->types + index;
+ return (*ps)->types + tindex;
}
/* Find a type given a type number. If the type has not been
ft = debug_get_field_type (minfo->dhandle, *fields);
if (ft == NULL)
- return FALSE;
+ {
+ free (name);
+ return FALSE;
+ }
dn = debug_get_type_name (minfo->dhandle, ft);
if (dn != NULL && strcmp (dn, name) == 0)
{
case 'M':
case 'O':
{
- bfd_boolean memberp, constp, volatilep;
+ bfd_boolean memberp;
debug_type class_type = DEBUG_TYPE_NULL;
debug_type *args;
bfd_boolean varargs;
const char *name;
memberp = **pp == 'M';
- constp = FALSE;
- volatilep = FALSE;
args = NULL;
varargs = FALSE;
{
if (**pp == 'C')
{
- constp = TRUE;
++*pp;
}
else if (**pp == 'V')
{
- volatilep = TRUE;
++*pp;
}
if (**pp != 'F')
case 'Q':
{
- const char *hold;
-
- hold = *pp;
if (! stab_demangle_qualified (minfo, pp, ptype))
return FALSE;
}
return NULL;
}
+ /* PR 13925: Cope if the demangler returns an empty
+ context for a function with no arguments. */
+ if (dc->u.s_binary.left == NULL)
+ break;
+
arg = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
NULL, &varargs);
if (arg == NULL)