/* stabs.c -- Parse stabs debugging information
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>.
This file is part of GNU Binutils.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
/* This file contains code which parses stabs debugging information.
The organization of this code is based on the gdb stabs reading
code. The job it does is somewhat different, because it is not
trying to identify the correct address for anything. */
-#include <stdio.h>
-
+#include "sysdep.h"
#include "bfd.h"
-#include "bucomm.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "demangle.h"
(void *, struct stab_handle *, const char *, bfd_boolean *, unsigned int);
static debug_type *stab_demangle_v3_argtypes
(void *, struct stab_handle *, const char *, bfd_boolean *);
+static debug_type *stab_demangle_v3_arglist
+ (void *, struct stab_handle *, struct demangle_component *, bfd_boolean *);
static debug_type stab_demangle_v3_arg
(void *, struct stab_handle *, struct demangle_component *, debug_type,
bfd_boolean *);
return FALSE;
break;
+ case 'Y':
+ /* SUNPro C++ Namespace =Yn0. */
+ /* Skip the namespace mapping, as it is not used now. */
+ if (*(++p) == 'n' && *(++p) == '0')
+ {
+ /* =Yn0name; */
+ while (*p != ';')
+ ++p;
+ ++p;
+ return TRUE;
+ }
+ /* TODO SUNPro C++ support:
+ Support default arguments after F,P parameters
+ Ya = Anonymous unions
+ YM,YD = Pointers to class members
+ YT,YI = Templates
+ YR = Run-time type information (RTTI) */
+
+ /* Fall through. */
+
default:
bad_stab (string);
return FALSE;
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];
#define ULLHIGH "01777777777777777777777;"
if (index_type == DEBUG_TYPE_NULL)
{
- if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0
- && strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0)
+ if (CONST_STRNEQ (s2, LLLOW)
+ && CONST_STRNEQ (s3, LLHIGH))
return debug_make_int_type (dhandle, 8, FALSE);
if (! ov2
&& n2 == 0
- && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0)
+ && CONST_STRNEQ (s3, ULLHIGH))
return debug_make_int_type (dhandle, 8, TRUE);
}
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. */
}
++*pp;
- /* For some odd reason, all forms of char put a c here. This is strange
- because no other type has this honor. We can safely ignore this because
- we actually determine 'char'acterness by the number of bits specified in
- the descriptor. */
- if (**pp == 'c')
+ /* OpenSolaris source code indicates that one of "cbv" characters
+ can come next and specify the intrinsic 'iformat' encoding.
+ 'c' is character encoding, 'b' is boolean encoding, and 'v' is
+ varargs encoding. This field can be safely ignored because
+ the type of the field is determined from the bitwidth extracted
+ below. */
+ if (**pp == 'c' || **pp == 'b' || **pp == 'v')
++*pp;
/* The first number appears to be the number of bytes occupied
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;
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"));
&& (ISDIGIT (argtypes[2])
|| argtypes[2] == 'Q'
|| argtypes[2] == 't'))
- || strncmp (argtypes, "__ct", 4) == 0);
+ || CONST_STRNEQ (argtypes, "__ct"));
is_constructor = (is_full_physname_constructor
|| (tagname != NULL
is_destructor = ((argtypes[0] == '_'
&& (argtypes[1] == '$' || argtypes[1] == '.')
&& argtypes[2] == '_')
- || strncmp (argtypes, "__dt", 4) == 0);
+ || CONST_STRNEQ (argtypes, "__dt"));
is_v3 = argtypes[0] == '_' && argtypes[1] == 'Z';
if (is_destructor || is_full_physname_constructor || is_v3)
*pp = scan + 2;
if (*pp - name >= 5
- && strncmp (name, "type", 4) == 0
+ && CONST_STRNEQ (name, "type")
&& (name[4] == '$' || name[4] == '.'))
{
const char *tem;
{
unsigned int len;
- if (! stab_demangle_get_count (pp, &len))
+ len = stab_demangle_count (pp);
+ if (len == 0)
{
stab_bad_demangle (orig);
return FALSE;
{
struct demangle_component *dc;
void *mem;
- unsigned int alloc, count;
debug_type *pargs;
dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem);
return NULL;
}
+ pargs = stab_demangle_v3_arglist (dhandle, info,
+ dc->u.s_binary.right->u.s_binary.right,
+ pvarargs);
+
+ free (mem);
+
+ return pargs;
+}
+
+/* Demangle an argument list in a struct demangle_component tree.
+ Returns a DEBUG_TYPE_NULL terminated array of argument types, and
+ sets *PVARARGS to indicate whether this is a varargs function. */
+
+static debug_type *
+stab_demangle_v3_arglist (void *dhandle, struct stab_handle *info,
+ struct demangle_component *arglist,
+ bfd_boolean *pvarargs)
+{
+ struct demangle_component *dc;
+ unsigned int alloc, count;
+ debug_type *pargs;
+
alloc = 10;
pargs = (debug_type *) xmalloc (alloc * sizeof *pargs);
*pvarargs = FALSE;
count = 0;
- for (dc = dc->u.s_binary.right->u.s_binary.right;
+ for (dc = arglist;
dc != NULL;
dc = dc->u.s_binary.right)
{
if (dc->type != DEMANGLE_COMPONENT_ARGLIST)
{
- fprintf (stderr, _("Unexpected type in demangle tree\n"));
- free (mem);
+ fprintf (stderr, _("Unexpected type in v3 arglist demangling\n"));
+ free (pargs);
return NULL;
}
*pvarargs = TRUE;
continue;
}
- free (mem);
+ free (pargs);
return NULL;
}
pargs[count] = DEBUG_TYPE_NULL;
- free (mem);
-
return pargs;
}
case DEMANGLE_COMPONENT_COMPLEX:
case DEMANGLE_COMPONENT_IMAGINARY:
case DEMANGLE_COMPONENT_VENDOR_TYPE:
- case DEMANGLE_COMPONENT_FUNCTION_TYPE:
case DEMANGLE_COMPONENT_ARRAY_TYPE:
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
case DEMANGLE_COMPONENT_ARGLIST:
default:
- fprintf (stderr, _("Unrecognized demangle component\n"));
+ fprintf (stderr, _("Unrecognized demangle component %d\n"),
+ (int) dc->type);
return NULL;
case DEMANGLE_COMPONENT_NAME:
return debug_make_reference_type (dhandle, dt);
}
+ case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+ {
+ debug_type *pargs;
+ bfd_boolean varargs;
+
+ if (dc->u.s_binary.left == NULL)
+ {
+ /* In this case the return type is actually unknown.
+ However, I'm not sure this will ever arise in practice;
+ normally an unknown return type would only appear at
+ the top level, which is handled above. */
+ dt = debug_make_void_type (dhandle);
+ }
+ else
+ dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL,
+ NULL);
+ if (dt == NULL)
+ return NULL;
+
+ pargs = stab_demangle_v3_arglist (dhandle, info,
+ dc->u.s_binary.right,
+ &varargs);
+ if (pargs == NULL)
+ return NULL;
+
+ return debug_make_function_type (dhandle, dt, pargs, varargs);
+ }
+
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
{
char *p;