/* stabs.c -- Parse stabs debugging information
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
This file is part of GNU Binutils.
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
trying to identify the correct address for anything. */
#include <stdio.h>
-#include <ctype.h>
#include "bfd.h"
#include "bucomm.h"
#include "libiberty.h"
+#include "safe-ctype.h"
#include "demangle.h"
#include "debug.h"
#include "budbg.h"
-
-/* Meaningless definition needs by aout64.h. FIXME. */
-#define BYTES_IN_WORD 4
-
+#include "filenames.h"
#include "aout/aout64.h"
#include "aout/stab_gnu.h"
struct stab_handle
{
- /* True if this is stabs in sections. */
- boolean sections;
- /* The type of the last stab symbol, so that we can detect N_SO
- pairs. */
- int last_type;
+ /* The BFD. */
+ bfd *abfd;
+ /* TRUE if this is stabs in sections. */
+ bfd_boolean sections;
+ /* The symbol table. */
+ asymbol **syms;
+ /* The number of symbols. */
+ long symcount;
+ /* The accumulated file name string. */
+ char *so_string;
+ /* The value of the last N_SO symbol. */
+ bfd_vma so_value;
/* The value of the start of the file, so that we can handle file
relative N_LBRAC and N_RBRAC symbols. */
bfd_vma file_start_offset;
int gcc_compiled;
/* Whether an N_OPT symbol was seen that was not generated by gcc,
so that we can detect the SunPRO compiler. */
- boolean n_opt_found;
+ bfd_boolean n_opt_found;
/* The main file name. */
char *main_filename;
- /* A stack of N_BINCL files. */
+ /* A stack of unfinished N_BINCL files. */
struct bincl_file *bincl_stack;
+ /* A list of finished N_BINCL files. */
+ struct bincl_file *bincl_list;
/* Whether we are inside a function or not. */
- boolean within_function;
+ bfd_boolean within_function;
+ /* The address of the end of the function, used if we have seen an
+ N_FUN symbol while in a function. This is -1 if we have not seen
+ an N_FUN (the normal case). */
+ bfd_vma function_end;
/* The depth of block nesting. */
int block_depth;
/* List of pending variable definitions. */
debug_type xcoff_types[XCOFF_TYPE_COUNT];
/* Undefined tags. */
struct stab_tag *tags;
+ /* Set by parse_stab_type if it sees a structure defined as a cross
+ reference to itself. Reset by parse_stab_type otherwise. */
+ bfd_boolean self_crossref;
};
/* A list of these structures is used to hold pending variable
debug_type type;
};
-static char *savestring PARAMS ((const char *, int));
-static bfd_vma parse_number PARAMS ((const char **, boolean *));
-static void bad_stab PARAMS ((const char *));
-static void warn_stab PARAMS ((const char *, const char *));
-static boolean parse_stab_string
- PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *));
+static char *savestring (const char *, int);
+static bfd_vma parse_number (const char **, bfd_boolean *);
+static void bad_stab (const char *);
+static void warn_stab (const char *, const char *);
+static bfd_boolean parse_stab_string
+ (void *, struct stab_handle *, int, int, bfd_vma, const char *);
static debug_type parse_stab_type
- PARAMS ((PTR, struct stab_handle *, const char *, const char **,
- debug_type **));
-static boolean parse_stab_type_number
- PARAMS ((const char **, int *));
+ (void *, struct stab_handle *, const char *, const char **, debug_type **);
+static bfd_boolean parse_stab_type_number (const char **, int *);
static debug_type parse_stab_range_type
- PARAMS ((PTR, struct stab_handle *, const char *, const char **,
- const int *));
-static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **));
-static debug_type parse_stab_sun_floating_type
- PARAMS ((PTR, const char **));
-static debug_type parse_stab_enum_type PARAMS ((PTR, const char **));
+ (void *, struct stab_handle *, const char *, const char **, const int *);
+static debug_type parse_stab_sun_builtin_type (void *, const char **);
+static debug_type parse_stab_sun_floating_type (void *, const char **);
+static debug_type parse_stab_enum_type (void *, const char **);
static debug_type parse_stab_struct_type
- PARAMS ((PTR, struct stab_handle *, const char *, const char **, boolean,
- const int *));
-static boolean parse_stab_baseclasses
- PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **));
-static boolean parse_stab_struct_fields
- PARAMS ((PTR, struct stab_handle *, const char **, debug_field **,
- boolean *));
-static boolean parse_stab_cpp_abbrev
- PARAMS ((PTR, struct stab_handle *, const char **, debug_field *));
-static boolean parse_stab_one_struct_field
- PARAMS ((PTR, struct stab_handle *, const char **, const char *,
- debug_field *, boolean *));
-static boolean parse_stab_members
- PARAMS ((PTR, struct stab_handle *, const char *, const char **,
- const int *, debug_method **));
+ (void *, struct stab_handle *, const char *, const char **,
+ bfd_boolean, const int *);
+static bfd_boolean parse_stab_baseclasses
+ (void *, struct stab_handle *, const char **, debug_baseclass **);
+static bfd_boolean parse_stab_struct_fields
+ (void *, struct stab_handle *, const char **, debug_field **, bfd_boolean *);
+static bfd_boolean parse_stab_cpp_abbrev
+ (void *, struct stab_handle *, const char **, debug_field *);
+static bfd_boolean parse_stab_one_struct_field
+ (void *, struct stab_handle *, const char **, const char *,
+ debug_field *, bfd_boolean *);
+static bfd_boolean parse_stab_members
+ (void *, struct stab_handle *, const char *, const char **, const int *,
+ debug_method **);
static debug_type parse_stab_argtypes
- PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *,
- debug_type, const char *, boolean, boolean, const char **));
-static boolean parse_stab_tilde_field
- PARAMS ((PTR, struct stab_handle *, const char **, const int *,
- debug_type *, boolean *));
+ (void *, struct stab_handle *, debug_type, const char *, const char *,
+ debug_type, const char *, bfd_boolean, bfd_boolean, const char **);
+static bfd_boolean parse_stab_tilde_field
+ (void *, struct stab_handle *, const char **, const int *, debug_type *,
+ bfd_boolean *);
static debug_type parse_stab_array_type
- PARAMS ((PTR, struct stab_handle *, const char **, boolean));
-static void push_bincl PARAMS ((struct stab_handle *, const char *));
-static const char *pop_bincl PARAMS ((struct stab_handle *));
-static boolean stab_record_variable
- PARAMS ((PTR, struct stab_handle *, const char *, debug_type,
- enum debug_var_kind, bfd_vma));
-static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *));
-static debug_type *stab_find_slot
- PARAMS ((struct stab_handle *, const int *));
-static debug_type stab_find_type
- PARAMS ((PTR, struct stab_handle *, const int *));
-static boolean stab_record_type
- PARAMS ((PTR, struct stab_handle *, const int *, debug_type));
+ (void *, struct stab_handle *, const char **, bfd_boolean);
+static void push_bincl (struct stab_handle *, const char *, bfd_vma);
+static const char *pop_bincl (struct stab_handle *);
+static bfd_boolean find_excl (struct stab_handle *, const char *, bfd_vma);
+static bfd_boolean stab_record_variable
+ (void *, struct stab_handle *, const char *, debug_type,
+ enum debug_var_kind, bfd_vma);
+static bfd_boolean stab_emit_pending_vars (void *, struct stab_handle *);
+static debug_type *stab_find_slot (struct stab_handle *, const int *);
+static debug_type stab_find_type (void *, struct stab_handle *, const int *);
+static bfd_boolean stab_record_type
+ (void *, struct stab_handle *, const int *, debug_type);
static debug_type stab_xcoff_builtin_type
- PARAMS ((PTR, struct stab_handle *, int));
+ (void *, struct stab_handle *, int);
static debug_type stab_find_tagged_type
- PARAMS ((PTR, struct stab_handle *, const char *, int,
- enum debug_type_kind));
+ (void *, struct stab_handle *, const char *, int, enum debug_type_kind);
static debug_type *stab_demangle_argtypes
- PARAMS ((PTR, struct stab_handle *, const char *, boolean *));
+ (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 *);
/* Save a string in memory. */
static char *
-savestring (start, len)
- const char *start;
- int len;
+savestring (const char *start, int len)
{
char *ret;
/* Read a number from a string. */
static bfd_vma
-parse_number (pp, poverflow)
- const char **pp;
- boolean *poverflow;
+parse_number (const char **pp, bfd_boolean *poverflow)
{
unsigned long ul;
const char *orig;
if (poverflow != NULL)
- *poverflow = false;
+ *poverflow = FALSE;
orig = *pp;
errno = 0;
ul = strtoul (*pp, (char **) pp, 0);
if (ul + 1 != 0 || errno == 0)
- return (bfd_vma) ul;
+ {
+ /* If bfd_vma is larger than unsigned long, and the number is
+ meant to be negative, we have to make sure that we sign
+ extend properly. */
+ if (*orig == '-')
+ return (bfd_vma) (bfd_signed_vma) (long) ul;
+ return (bfd_vma) ul;
+ }
/* Note that even though strtoul overflowed, it should have set *pp
to the end of the number, which is where we want it. */
-
if (sizeof (bfd_vma) > sizeof (unsigned long))
{
const char *p;
- boolean neg;
+ bfd_boolean neg;
int base;
bfd_vma over, lastdig;
- boolean overflow;
+ bfd_boolean overflow;
bfd_vma v;
/* Our own version of strtoul, for a bfd_vma. */
-
p = orig;
- neg = false;
+ neg = FALSE;
if (*p == '+')
++p;
else if (*p == '-')
{
- neg = true;
+ neg = TRUE;
++p;
}
over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
- overflow = false;
+ overflow = FALSE;
v = 0;
while (1)
{
int d;
d = *p++;
- if (isdigit ((unsigned char) d))
+ if (ISDIGIT (d))
d -= '0';
- else if (isupper ((unsigned char) d))
+ else if (ISUPPER (d))
d -= 'A';
- else if (islower ((unsigned char) d))
+ else if (ISLOWER (d))
d -= 'a';
else
break;
if (v > over || (v == over && (bfd_vma) d > lastdig))
{
- overflow = true;
+ overflow = TRUE;
break;
}
}
/* If we get here, the number is too large to represent in a
bfd_vma. */
-
if (poverflow != NULL)
- *poverflow = true;
+ *poverflow = TRUE;
else
- warn_stab (orig, "numeric overflow");
+ warn_stab (orig, _("numeric overflow"));
return 0;
}
/* Give an error for a bad stab string. */
static void
-bad_stab (p)
- const char *p;
+bad_stab (const char *p)
{
- fprintf (stderr, "Bad stab: %s\n", p);
+ fprintf (stderr, _("Bad stab: %s\n"), p);
}
/* Warn about something in a stab string. */
static void
-warn_stab (p, err)
- const char *p;
- const char *err;
+warn_stab (const char *p, const char *err)
{
- fprintf (stderr, "Warning: %s: %s\n", err, p);
+ fprintf (stderr, _("Warning: %s: %s\n"), err, p);
}
/* Create a handle to parse stabs symbols with. */
-/*ARGSUSED*/
-PTR
-start_stab (dhandle, sections)
- PTR dhandle;
- boolean sections;
+void *
+start_stab (void *dhandle ATTRIBUTE_UNUSED, bfd *abfd, bfd_boolean sections,
+ asymbol **syms, long symcount)
{
struct stab_handle *ret;
ret = (struct stab_handle *) xmalloc (sizeof *ret);
memset (ret, 0, sizeof *ret);
+ ret->abfd = abfd;
ret->sections = sections;
+ ret->syms = syms;
+ ret->symcount = symcount;
ret->files = 1;
ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
ret->file_types[0] = NULL;
- return (PTR) ret;
+ ret->function_end = (bfd_vma) -1;
+ return (void *) ret;
}
/* When we have processed all the stabs information, we need to go
through and fill in all the undefined tags. */
-boolean
-finish_stab (dhandle, handle)
- PTR dhandle;
- PTR handle;
+bfd_boolean
+finish_stab (void *dhandle, void *handle)
{
struct stab_handle *info = (struct stab_handle *) handle;
struct stab_tag *st;
if (info->within_function)
{
- if (! debug_end_function (dhandle, (bfd_vma) -1))
- return false;
- info->within_function = false;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, info->function_end))
+ return FALSE;
+ info->within_function = FALSE;
+ info->function_end = (bfd_vma) -1;
}
for (st = info->tags; st != NULL; st = st->next)
kind = DEBUG_KIND_STRUCT;
st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
if (st->slot == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
}
- if (info->pending)
- fprintf (stderr, "Left over pending variables in stabs debugging\n");
-
- return true;
+ return TRUE;
}
/* Handle a single stabs symbol. */
-boolean
-parse_stab (dhandle, handle, type, desc, value, string)
- PTR dhandle;
- PTR handle;
- int type;
- int desc;
- bfd_vma value;
- const char *string;
+bfd_boolean
+parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
+ const char *string)
{
struct stab_handle *info = (struct stab_handle *) handle;
+ /* gcc will emit two N_SO strings per compilation unit, one for the
+ directory name and one for the file name. We just collect N_SO
+ strings as we see them, and start the new compilation unit when
+ we see a non N_SO symbol. */
+ if (info->so_string != NULL
+ && (type != N_SO || *string == '\0' || value != info->so_value))
+ {
+ if (! debug_set_filename (dhandle, info->so_string))
+ return FALSE;
+ info->main_filename = info->so_string;
+
+ info->gcc_compiled = 0;
+ info->n_opt_found = FALSE;
+
+ /* Generally, for stabs in the symbol table, the N_LBRAC and
+ N_RBRAC symbols are relative to the N_SO symbol value. */
+ if (! info->sections)
+ info->file_start_offset = info->so_value;
+
+ /* We need to reset the mapping from type numbers to types. We
+ can't free the old mapping, because of the use of
+ debug_make_indirect_type. */
+ info->files = 1;
+ info->file_types = ((struct stab_types **)
+ xmalloc (sizeof *info->file_types));
+ info->file_types[0] = NULL;
+
+ info->so_string = NULL;
+
+ /* Now process whatever type we just got. */
+ }
+
switch (type)
{
case N_FN:
if (! info->within_function)
{
- fprintf (stderr, "N_LBRAC not within function\n");
- return false;
+ fprintf (stderr, _("N_LBRAC not within function\n"));
+ return FALSE;
}
/* Start an inner lexical block. */
(value
+ info->file_start_offset
+ info->function_start_offset)))
- return false;
+ return FALSE;
/* Emit any pending variable definitions. */
if (! stab_emit_pending_vars (dhandle, info))
- return false;
+ return FALSE;
++info->block_depth;
break;
if we do, we probably need to emit them before closing the
block. */
if (! stab_emit_pending_vars (dhandle, info))
- return false;
+ return FALSE;
/* End an inner lexical block. */
if (! debug_end_block (dhandle,
(value
+ info->file_start_offset
+ info->function_start_offset)))
- return false;
+ return FALSE;
--info->block_depth;
if (info->block_depth < 0)
{
- fprintf (stderr, "Too many N_RBRACs\n");
- return false;
+ fprintf (stderr, _("Too many N_RBRACs\n"));
+ return FALSE;
}
break;
case N_SO:
- /* Start a file. If we get two in a row, the first is the
- directory name. An empty string is emitted by gcc at the end
- of a compilation unit. */
- if (*string == '\0')
+ /* This always ends a function. */
+ if (info->within_function)
{
- if (info->within_function)
- {
- if (! debug_end_function (dhandle, value))
- return false;
- info->within_function = false;
- }
- return true;
+ bfd_vma endval;
+
+ endval = value;
+ if (*string != '\0'
+ && info->function_end != (bfd_vma) -1
+ && info->function_end < endval)
+ endval = info->function_end;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, endval))
+ return FALSE;
+ info->within_function = FALSE;
+ info->function_end = (bfd_vma) -1;
}
- info->gcc_compiled = 0;
- info->n_opt_found = false;
- if (info->last_type == N_SO)
- {
- char *o;
- if (! debug_append_filename (dhandle, string))
- return false;
- o = info->main_filename;
- info->main_filename = concat (o, string, (const char *) NULL);
- free (o);
- }
+ /* An empty string is emitted by gcc at the end of a compilation
+ unit. */
+ if (*string == '\0')
+ return TRUE;
+
+ /* Just accumulate strings until we see a non N_SO symbol. If
+ the string starts with a directory separator or some other
+ form of absolute path specification, we discard the previously
+ accumulated strings. */
+ if (info->so_string == NULL)
+ info->so_string = xstrdup (string);
else
{
- if (info->within_function)
- {
- if (! debug_end_function (dhandle, value))
- return false;
- info->within_function = false;
- }
- if (! debug_set_filename (dhandle, string))
- return false;
- if (info->main_filename != NULL)
- free (info->main_filename);
- info->main_filename = xstrdup (string);
-
- /* Generally, for stabs in the symbol table, the N_LBRAC and
- N_RBRAC symbols are relative to the N_SO symbol value. */
- if (! info->sections)
- info->file_start_offset = value;
-
- /* We need to reset the mapping from type numbers to types.
- We can't free the old mapping, because of the use of
- debug_make_indirect_type. */
- info->files = 1;
- info->file_types = ((struct stab_types **)
- xmalloc (sizeof *info->file_types));
- info->file_types[0] = NULL;
+ char *f;
+
+ f = info->so_string;
+
+ if (IS_ABSOLUTE_PATH (string))
+ info->so_string = xstrdup (string);
+ else
+ info->so_string = concat (info->so_string, string,
+ (const char *) NULL);
+ free (f);
}
+
+ info->so_value = value;
+
break;
case N_SOL:
/* Start an include file. */
if (! debug_start_source (dhandle, string))
- return false;
+ return FALSE;
break;
case N_BINCL:
/* Start an include file which may be replaced. */
- push_bincl (info, string);
+ push_bincl (info, string, value);
if (! debug_start_source (dhandle, string))
- return false;
+ return FALSE;
break;
case N_EINCL:
/* End an N_BINCL include. */
if (! debug_start_source (dhandle, pop_bincl (info)))
- return false;
+ return FALSE;
break;
case N_EXCL:
/* This is a duplicate of a header file named by N_BINCL which
was eliminated by the linker. */
- ++info->files;
- info->file_types = ((struct stab_types **)
- xrealloc ((PTR) info->file_types,
- (info->files
- * sizeof *info->file_types)));
- info->file_types[info->files - 1] = NULL;
+ if (! find_excl (info, string, value))
+ return FALSE;
break;
case N_SLINE:
if (! debug_record_line (dhandle, desc,
- value + info->function_start_offset))
- return false;
+ value + (info->within_function
+ ? info->function_start_offset : 0)))
+ return FALSE;
break;
case N_BCOMM:
if (! debug_start_common_block (dhandle, string))
- return false;
+ return FALSE;
break;
case N_ECOMM:
if (! debug_end_common_block (dhandle, string))
- return false;
+ return FALSE;
break;
+ case N_FUN:
+ if (*string == '\0')
+ {
+ if (info->within_function)
+ {
+ /* This always marks the end of a function; we don't
+ need to worry about info->function_end. */
+ if (info->sections)
+ value += info->function_start_offset;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, value))
+ return FALSE;
+ info->within_function = FALSE;
+ info->function_end = (bfd_vma) -1;
+ }
+ break;
+ }
+
+ /* A const static symbol in the .text section will have an N_FUN
+ entry. We need to use these to mark the end of the function,
+ in case we are looking at gcc output before it was changed to
+ always emit an empty N_FUN. We can't call debug_end_function
+ here, because it might be a local static symbol. */
+ if (info->within_function
+ && (info->function_end == (bfd_vma) -1
+ || value < info->function_end))
+ info->function_end = value;
+
+ /* Fall through. */
/* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
symbols, and if it does not start with :S, gdb relocates the
value to the start of the section. gcc always seems to use
:S, so we don't worry about this. */
+ /* Fall through. */
default:
{
const char *colon;
{
if (info->within_function)
{
- if (! debug_end_function (dhandle, value))
- return false;
+ bfd_vma endval;
+
+ endval = value;
+ if (info->function_end != (bfd_vma) -1
+ && info->function_end < endval)
+ endval = info->function_end;
+ if (! stab_emit_pending_vars (dhandle, info)
+ || ! debug_end_function (dhandle, endval))
+ return FALSE;
+ info->function_end = (bfd_vma) -1;
}
/* For stabs in sections, line numbers and block addresses
are offsets from the start of the function. */
if (info->sections)
info->function_start_offset = value;
- info->within_function = true;
+ info->within_function = TRUE;
}
if (! parse_stab_string (dhandle, info, type, desc, value, string))
- return false;
+ return FALSE;
}
break;
else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
info->gcc_compiled = 1;
else
- info->n_opt_found = true;
+ info->n_opt_found = TRUE;
break;
case N_OBJ:
case N_ENDM:
case N_MAIN:
+ case N_WARNING:
break;
}
- info->last_type = type;
-
- return true;
+ return TRUE;
}
/* Parse the stabs string. */
-static boolean
-parse_stab_string (dhandle, info, stabtype, desc, value, string)
- PTR dhandle;
- struct stab_handle *info;
- int stabtype;
- int desc;
- bfd_vma value;
- const char *string;
+static bfd_boolean
+parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
+ int desc, bfd_vma value, const char *string)
{
const char *p;
char *name;
int type;
debug_type dtype;
- boolean synonym;
+ bfd_boolean synonym;
+ bfd_boolean self_crossref;
unsigned int lineno;
debug_type *slot;
p = strchr (string, ':');
if (p == NULL)
- return true;
+ return TRUE;
while (p[1] == ':')
{
if (p == NULL)
{
bad_stab (string);
- return false;
+ return FALSE;
}
}
/* SunPRO (3.0 at least) static variable encoding. */
break;
default:
- warn_stab (string, "unknown C++ encoded name");
+ warn_stab (string, _("unknown C++ encoded name"));
break;
}
}
}
++p;
- if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
+ if (ISDIGIT (*p) || *p == '(' || *p == '-')
type = 'l';
else
type = *p++;
if (*p != '=')
{
bad_stab (string);
- return false;
+ return FALSE;
}
++p;
switch (*p++)
case 'r':
/* Floating point constant. */
if (! debug_record_float_const (dhandle, name, atof (p)))
- return false;
+ return FALSE;
break;
case 'i':
/* Integer constant. */
other languages probably should have at least unsigned as
well as signed constants. */
if (! debug_record_int_const (dhandle, name, atoi (p)))
- return false;
+ return FALSE;
break;
case 'e':
/* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
&p, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (*p != ',')
{
bad_stab (string);
- return false;
+ return FALSE;
}
if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
- return false;
+ return FALSE;
break;
default:
bad_stab (string);
- return false;
+ return FALSE;
}
break;
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
&p, (debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! debug_record_label (dhandle, name, dtype, value))
- return false;
+ return FALSE;
break;
case 'f':
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
- return false;
+ return FALSE;
/* Sun acc puts declared types of arguments here. We don't care
about their actual types (FIXME -- we should remember the whole
if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL)
== DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
}
break;
case 'G':
- /* A global symbol. The value must be extracted from the symbol
- table. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return false;
- if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
- (bfd_vma) -1))
- return false;
+ {
+ char leading;
+ long c;
+ asymbol **ps;
+
+ /* A global symbol. The value must be extracted from the
+ symbol table. */
+ dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
+ (debug_type **) NULL);
+ if (dtype == DEBUG_TYPE_NULL)
+ return FALSE;
+ leading = bfd_get_symbol_leading_char (info->abfd);
+ for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
+ {
+ const char *n;
+
+ n = bfd_asymbol_name (*ps);
+ if (leading != '\0' && *n == leading)
+ ++n;
+ if (*n == *name && strcmp (n, name) == 0)
+ break;
+ }
+ if (c > 0)
+ value = bfd_asymbol_value (*ps);
+ if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
+ value))
+ return FALSE;
+ }
break;
/* This case is faked by a conditional above, when there is no
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
value))
- return false;
+ return FALSE;
break;
case 'p':
debug_type ftype;
ftype = debug_make_function_type (dhandle, dtype,
- (debug_type *) NULL, false);
+ (debug_type *) NULL, FALSE);
dtype = debug_make_pointer_type (dhandle, ftype);
}
}
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
value))
- return false;
+ return FALSE;
/* FIXME: At this point gdb considers rearranging the parameter
address on a big endian machine if it is smaller than an int.
We have no way to do that, since we don't really know much
about the target. */
-
break;
case 'P':
if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL)
== DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
}
break;
}
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
value))
- return false;
+ return FALSE;
break;
case 'r':
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
value))
- return false;
+ return FALSE;
/* FIXME: At this point gdb checks to combine pairs of 'p' and
'r' stabs into a single 'P' stab. */
-
break;
case 'S':
- /* Static symbol at top level of file */
+ /* Static symbol at top level of file. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
value))
- return false;
+ return FALSE;
break;
case 't':
/* A typedef. */
dtype = parse_stab_type (dhandle, info, name, &p, &slot);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (name == NULL)
{
/* A nameless type. Nothing to do. */
- return true;
+ return TRUE;
}
dtype = debug_name_type (dhandle, name, dtype);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (slot != NULL)
*slot = dtype;
by 't' which means we are typedef'ing it as well. */
if (*p != 't')
{
- synonym = false;
- /* FIXME: gdb sets synonym to true if the current language
+ synonym = FALSE;
+ /* FIXME: gdb sets synonym to TRUE if the current language
is C++. */
}
else
{
- synonym = true;
+ synonym = TRUE;
++p;
}
dtype = parse_stab_type (dhandle, info, name, &p, &slot);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (name == NULL)
- return true;
+ return TRUE;
+
+ /* INFO->SELF_CROSSREF is set by parse_stab_type if this type is
+ a cross reference to itself. These are generated by some
+ versions of g++. */
+ self_crossref = info->self_crossref;
dtype = debug_tag_type (dhandle, name, dtype);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (slot != NULL)
*slot = dtype;
/* See if we have a cross reference to this tag which we can now
- fill in. */
- {
- register struct stab_tag **pst;
+ fill in. Avoid filling in a cross reference to ourselves,
+ because that would lead to circular debugging information. */
+ if (! self_crossref)
+ {
+ register struct stab_tag **pst;
- for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
- {
- if ((*pst)->name[0] == name[0]
- && strcmp ((*pst)->name, name) == 0)
- {
- (*pst)->slot = dtype;
- *pst = (*pst)->next;
- break;
- }
- }
- }
+ for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
+ {
+ if ((*pst)->name[0] == name[0]
+ && strcmp ((*pst)->name, name) == 0)
+ {
+ (*pst)->slot = dtype;
+ *pst = (*pst)->next;
+ break;
+ }
+ }
+ }
if (synonym)
{
dtype = debug_name_type (dhandle, name, dtype);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (slot != NULL)
*slot = dtype;
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
/* FIXME: gdb checks os9k_stabs here. */
if (! stab_record_variable (dhandle, info, name, dtype,
DEBUG_LOCAL_STATIC, value))
- return false;
+ return FALSE;
break;
case 'v':
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
value))
- return false;
+ return FALSE;
break;
case 'a':
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
value))
- return false;
+ return FALSE;
break;
case 'X':
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
(debug_type **) NULL);
if (dtype == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
value))
- return false;
+ return FALSE;
break;
default:
bad_stab (string);
- return false;
+ return FALSE;
}
/* FIXME: gdb converts structure values to structure pointers in a
couple of cases, depending upon the target. */
- return true;
+ return TRUE;
}
/* Parse a stabs type. The typename argument is non-NULL if this is a
store the slot used if the type is being defined. */
static debug_type
-parse_stab_type (dhandle, info, typename, pp, slotp)
- PTR 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 *typename, const char **pp, debug_type **slotp)
{
const char *orig;
int typenums[2];
int size;
- boolean stringp;
+ bfd_boolean stringp;
int descriptor;
debug_type dtype;
orig = *pp;
size = -1;
- stringp = false;
+ stringp = FALSE;
+
+ info->self_crossref = FALSE;
/* Read type number if present. The type number may be omitted.
for instance in a two-dimensional array declared with type
"ar1;1;10;ar1;1;10;4". */
- if (! isdigit ((unsigned char) **pp) && **pp != '(' && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '(' && **pp != '-')
{
/* 'typenums=' not present, type is anonymous. Read and return
the definition, but don't put it in the type vector. */
return DEBUG_TYPE_NULL;
if (**pp != '=')
- {
- /* Type is not being defined here. Either it already
- exists, or this is a forward reference to it. */
- return stab_find_type (dhandle, info, typenums);
- }
+ /* Type is not being defined here. Either it already
+ exists, or this is a forward reference to it. */
+ return stab_find_type (dhandle, info, typenums);
/* Only set the slot if the type is being defined. This means
that the mapping from type numbers to types will only record
const char *p = *pp + 1;
const char *attr;
- if (isdigit ((unsigned char) *p) || *p == '(' || *p == '-')
- {
- /* Member type. */
- break;
- }
+ if (ISDIGIT (*p) || *p == '(' || *p == '-')
+ /* Member type. */
+ break;
/* Type attributes. */
attr = p;
{
case 's':
size = atoi (attr + 1);
+ size /= 8; /* Size is in bits. We store it in bytes. */
if (size <= 0)
size = -1;
break;
case 'S':
- stringp = true;
+ stringp = TRUE;
break;
default:
const char *q1, *q2, *p;
/* A cross reference to another type. */
-
switch (**pp)
{
case 's':
default:
/* Complain and keep going, so compilers can invent new
cross-reference types. */
- warn_stab (orig, "unrecognized cross reference type");
+ warn_stab (orig, _("unrecognized cross reference type"));
code = DEBUG_KIND_STRUCT;
break;
}
bad_stab (orig);
return DEBUG_TYPE_NULL;
}
- while (q1 != NULL && p > q1 && p[1] == ':')
+ if (q1 != NULL && p > q1 && p[1] == ':')
{
- q2 = strchr (q1, '>');
- if (q2 == NULL || q2 < p)
- break;
- p += 2;
- p = strchr (p, ':');
- if (p == NULL)
+ int nest = 0;
+
+ for (q2 = q1; *q2 != '\0'; ++q2)
+ {
+ if (*q2 == '<')
+ ++nest;
+ else if (*q2 == '>')
+ --nest;
+ else if (*q2 == ':' && nest == 0)
+ break;
+ }
+ p = q2;
+ if (*p != ':')
{
bad_stab (orig);
return DEBUG_TYPE_NULL;
}
}
+ /* Some versions of g++ can emit stabs like
+ 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')
+ info->self_crossref = TRUE;
+
dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
*pp = p + 1;
int xtypenums[2];
/* This type is defined as another type. */
-
(*pp)--;
hold = *pp;
(dhandle,
parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL),
- (debug_type *) NULL, false));
+ (debug_type *) NULL, FALSE));
break;
case 'k':
++*pp;
dtype = debug_make_method_type (dhandle, return_type,
DEBUG_TYPE_NULL,
- (debug_type *) NULL, false);
+ (debug_type *) NULL, FALSE);
}
else
{
debug_type *args;
unsigned int n;
unsigned int alloc;
- boolean varargs;
+ bfd_boolean varargs;
domain = parse_stab_type (dhandle, info, (const char *) NULL,
pp, (debug_type **) NULL);
{
alloc += 10;
args = ((debug_type *)
- xrealloc ((PTR) args, alloc * sizeof *args));
+ xrealloc (args, alloc * sizeof *args));
}
args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
the void type. */
if (n == 0
|| debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
- varargs = true;
+ varargs = TRUE;
else
{
--n;
- varargs = false;
+ varargs = FALSE;
}
args[n] = DEBUG_TYPE_NULL;
if (size != -1)
{
if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
- return false;
+ return DEBUG_TYPE_NULL;
}
return dtype;
single number N is equivalent to (0,N). Return the two numbers by
storing them in the vector TYPENUMS. */
-static boolean
-parse_stab_type_number (pp, typenums)
- const char **pp;
- int *typenums;
+static bfd_boolean
+parse_stab_type_number (const char **pp, int *typenums)
{
const char *orig;
if (**pp != '(')
{
typenums[0] = 0;
- typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+ typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
}
else
{
++*pp;
- typenums[0] = (int) parse_number (pp, (boolean *) NULL);
+ typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ',')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
- typenums[1] = (int) parse_number (pp, (boolean *) NULL);
+ typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ')')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
}
- return true;
+ return TRUE;
}
/* Parse a range type. */
static debug_type
-parse_stab_range_type (dhandle, info, typename, pp, typenums)
- PTR 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 *typename, const char **pp, const int *typenums)
{
const char *orig;
int rangenums[2];
- boolean self_subrange;
+ bfd_boolean self_subrange;
debug_type index_type;
const char *s2, *s3;
bfd_signed_vma n2, n3;
- boolean ov2, ov3;
+ bfd_boolean ov2, ov3;
orig = *pp;
{
/* gcc will emit range stabs for long long types. Handle this
as a special case. FIXME: This needs to be more general. */
-#define LLLOW "01000000000000000000000;"
-#define LLHIGH "0777777777777777777777;"
+#define LLLOW "01000000000000000000000;"
+#define LLHIGH "0777777777777777777777;"
#define ULLHIGH "01777777777777777777777;"
if (index_type == DEBUG_TYPE_NULL)
{
if (strncmp (s2, LLLOW, sizeof LLLOW - 1) == 0
&& strncmp (s3, LLHIGH, sizeof LLHIGH - 1) == 0)
- return debug_make_int_type (dhandle, 8, false);
+ return debug_make_int_type (dhandle, 8, FALSE);
if (! ov2
&& n2 == 0
&& strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0)
- return debug_make_int_type (dhandle, 8, true);
+ return debug_make_int_type (dhandle, 8, TRUE);
}
- warn_stab (orig, "numeric overflow");
+ warn_stab (orig, _("numeric overflow"));
}
if (index_type == DEBUG_TYPE_NULL)
if (self_subrange && n2 == 0 && n3 == 0)
return debug_make_void_type (dhandle);
+ /* A type defined as a subrange of itself, with n2 positive and
+ n3 zero, is a complex type, and n2 is the number of bytes. */
+ if (self_subrange && n3 == 0 && n2 > 0)
+ return debug_make_complex_type (dhandle, n2);
+
/* If n3 is zero and n2 is positive, this is a floating point
type, and n2 is the number of bytes. */
if (n3 == 0 && n2 > 0)
if (typename != NULL)
{
if (strcmp (typename, "long long int") == 0)
- return debug_make_int_type (dhandle, 8, false);
+ return debug_make_int_type (dhandle, 8, FALSE);
else if (strcmp (typename, "long long unsigned int") == 0)
- return debug_make_int_type (dhandle, 8, true);
+ return debug_make_int_type (dhandle, 8, TRUE);
}
/* FIXME: The size here really depends upon the target. */
- return debug_make_int_type (dhandle, 4, true);
+ return debug_make_int_type (dhandle, 4, TRUE);
}
/* A range of 0 to 127 is char. */
if (self_subrange && n2 == 0 && n3 == 127)
- return debug_make_int_type (dhandle, 1, false);
+ return debug_make_int_type (dhandle, 1, FALSE);
/* FIXME: gdb checks for the language CHILL here. */
if (n2 == 0)
{
if (n3 < 0)
- return debug_make_int_type (dhandle, - n3, true);
+ return debug_make_int_type (dhandle, - n3, TRUE);
else if (n3 == 0xff)
- return debug_make_int_type (dhandle, 1, true);
+ return debug_make_int_type (dhandle, 1, TRUE);
else if (n3 == 0xffff)
- return debug_make_int_type (dhandle, 2, true);
- /* -1 is used for the upper bound of (4 byte) "unsigned int"
- and "unsigned long", and we already checked for that, so
- don't need to test for it here. */
+ return debug_make_int_type (dhandle, 2, TRUE);
+ else if (n3 == (bfd_signed_vma) 0xffffffff)
+ return debug_make_int_type (dhandle, 4, TRUE);
+#ifdef BFD64
+ else if (n3 == ((((bfd_signed_vma) 0xffffffff) << 32) | 0xffffffff))
+ return debug_make_int_type (dhandle, 8, TRUE);
+#endif
}
else if (n3 == 0
&& n2 < 0
&& (self_subrange || n2 == -8))
- return debug_make_int_type (dhandle, - n2, true);
- else if (n2 == - n3 - 1)
+ return debug_make_int_type (dhandle, - n2, TRUE);
+ else if (n2 == - n3 - 1 || n2 == n3 + 1)
{
if (n3 == 0x7f)
- return debug_make_int_type (dhandle, 1, false);
+ return debug_make_int_type (dhandle, 1, FALSE);
else if (n3 == 0x7fff)
- return debug_make_int_type (dhandle, 2, false);
+ return debug_make_int_type (dhandle, 2, FALSE);
else if (n3 == 0x7fffffff)
- return debug_make_int_type (dhandle, 4, false);
+ return debug_make_int_type (dhandle, 4, FALSE);
+#ifdef BFD64
+ else if (n3 == ((((bfd_vma) 0x7fffffff) << 32) | 0xffffffff))
+ return debug_make_int_type (dhandle, 8, FALSE);
+#endif
}
}
{
/* Does this actually ever happen? Is that why we are worrying
about dealing with it rather than just calling error_type? */
- warn_stab (orig, "missing index type");
- index_type = debug_make_int_type (dhandle, 4, false);
+ warn_stab (orig, _("missing index type"));
+ index_type = debug_make_int_type (dhandle, 4, FALSE);
}
return debug_make_range_type (dhandle, index_type, n2, n3);
FIXME. */
static debug_type
-parse_stab_sun_builtin_type (dhandle, pp)
- PTR dhandle;
- const char **pp;
+parse_stab_sun_builtin_type (void *dhandle, const char **pp)
{
const char *orig;
- boolean unsignedp;
+ bfd_boolean unsignedp;
bfd_vma bits;
orig = *pp;
switch (**pp)
{
case 's':
- unsignedp = false;
+ unsignedp = FALSE;
break;
case 'u':
- unsignedp = true;
+ unsignedp = TRUE;
break;
default:
bad_stab (orig);
by this type, except that unsigned short is 4 instead of 2.
Since this information is redundant with the third number,
we will ignore it. */
- (void) parse_number (pp, (boolean *) NULL);
+ (void) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
}
++*pp;
- /* The second number is always 0, so ignore it too. */
- (void) parse_number (pp, (boolean *) NULL);
+ /* The second number is always 0, so ignore it too. */
+ (void) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
}
++*pp;
- /* The third number is the number of bits for this type. */
- bits = parse_number (pp, (boolean *) NULL);
+ /* The third number is the number of bits for this type. */
+ bits = parse_number (pp, (bfd_boolean *) NULL);
/* The type *should* end with a semicolon. If it are embedded
in a larger type the semicolon may be the only way to know where
/* Parse a builtin floating type generated by the Sun compiler. */
static debug_type
-parse_stab_sun_floating_type (dhandle, pp)
- PTR dhandle;
- const char **pp;
+parse_stab_sun_floating_type (void *dhandle, const char **pp)
{
const char *orig;
bfd_vma details;
/* The first number has more details about the type, for example
FN_COMPLEX. */
- details = parse_number (pp, (boolean *) NULL);
+ details = parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
}
/* The second number is the number of bytes occupied by this type */
- bytes = parse_number (pp, (boolean *) NULL);
+ bytes = parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
|| details == NF_COMPLEX32)
return debug_make_complex_type (dhandle, bytes);
- return debug_make_float_type (dhandle, bytes);
+ return debug_make_float_type (dhandle, bytes);
}
/* Handle an enum type. */
static debug_type
-parse_stab_enum_type (dhandle, pp)
- PTR dhandle;
- const char **pp;
+parse_stab_enum_type (void *dhandle, const char **pp)
{
const char *orig;
const char **names;
name = savestring (*pp, p - *pp);
*pp = p + 1;
- val = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ',')
{
bad_stab (orig);
{
alloc += 10;
names = ((const char **)
- xrealloc ((PTR) names, alloc * sizeof *names));
+ xrealloc (names, alloc * sizeof *names));
values = ((bfd_signed_vma *)
- xrealloc ((PTR) values, alloc * sizeof *values));
+ xrealloc (values, alloc * sizeof *values));
}
names[n] = name;
describing the type.
PP points to a character pointer that points to the next unconsumed token
- in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
+ in the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
*PP will point to "4a:1,0,32;;". */
static debug_type
-parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums)
- PTR dhandle;
- struct stab_handle *info;
- const char *tagname;
- const char **pp;
- boolean structp;
- const int *typenums;
+parse_stab_struct_type (void *dhandle, struct stab_handle *info,
+ const char *tagname, const char **pp,
+ bfd_boolean structp, const int *typenums)
{
const char *orig;
bfd_vma size;
debug_baseclass *baseclasses;
debug_field *fields;
- boolean statics;
+ bfd_boolean statics;
debug_method *methods;
debug_type vptrbase;
- boolean ownvptr;
+ bfd_boolean ownvptr;
orig = *pp;
/* Get the size. */
- size = parse_number (pp, (boolean *) NULL);
+ size = parse_number (pp, (bfd_boolean *) NULL);
/* Get the other information. */
if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
the type for the base class, and a terminating semicolon.
A typical example, with two base classes, would be "!2,020,19;0264,21;".
- ^^ ^ ^ ^ ^ ^ ^
+ ^^ ^ ^ ^ ^ ^ ^
Baseclass information marker __________________|| | | | | | |
Number of baseclasses __________________________| | | | | | |
Visibility specifiers (2) ________________________| | | | | |
Offset in bits from start of class ________________________| |
Type number of base class ____________________________________|
- Return true for success, false for failure. */
+ Return TRUE for success, FALSE for failure. */
-static boolean
-parse_stab_baseclasses (dhandle, info, pp, retp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- debug_baseclass **retp;
+static bfd_boolean
+parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
+ const char **pp, debug_baseclass **retp)
{
const char *orig;
unsigned int c, i;
if (**pp != '!')
{
/* No base classes. */
- return true;
+ return TRUE;
}
++*pp;
- c = (unsigned int) parse_number (pp, (boolean *) NULL);
+ c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ',')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
for (i = 0; i < c; i++)
{
- boolean virtual;
+ bfd_boolean virtual;
enum debug_visibility visibility;
bfd_vma bitpos;
debug_type type;
switch (**pp)
{
case '0':
- virtual = false;
+ virtual = FALSE;
break;
case '1':
- virtual = true;
+ virtual = TRUE;
break;
default:
- warn_stab (orig, "unknown virtual character for baseclass");
- virtual = false;
+ warn_stab (orig, _("unknown virtual character for baseclass"));
+ virtual = FALSE;
break;
}
++*pp;
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
default:
- warn_stab (orig, "unknown visibility character for baseclass");
+ warn_stab (orig, _("unknown visibility character for baseclass"));
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
}
/* The remaining value is the bit offset of the portion of the
object corresponding to this baseclass. Always zero in the
absence of multiple inheritance. */
- bitpos = parse_number (pp, (boolean *) NULL);
+ bitpos = parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ',')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
visibility);
if (classes[i] == DEBUG_BASECLASS_NULL)
- return false;
+ return FALSE;
if (**pp != ';')
- return false;
+ return FALSE;
++*pp;
}
*retp = classes;
- return true;
+ return TRUE;
}
/* Read struct or class data fields. They have the form:
- NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
+ NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
At the end, we see a semicolon instead of a field.
The optional VISIBILITY is one of:
- '/0' (VISIBILITY_PRIVATE)
+ '/0' (VISIBILITY_PRIVATE)
'/1' (VISIBILITY_PROTECTED)
'/2' (VISIBILITY_PUBLIC)
'/9' (VISIBILITY_IGNORE)
Returns 1 for success, 0 for failure. */
-static boolean
-parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- debug_field **retp;
- boolean *staticsp;
+static bfd_boolean
+parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
+ const char **pp, debug_field **retp,
+ bfd_boolean *staticsp)
{
const char *orig;
const char *p;
unsigned int alloc;
*retp = NULL;
- *staticsp = false;
+ *staticsp = FALSE;
orig = *pp;
{
alloc += 10;
fields = ((debug_field *)
- xrealloc ((PTR) fields, alloc * sizeof *fields));
+ xrealloc (fields, alloc * sizeof *fields));
}
/* If it starts with CPLUS_MARKER it is a special abbreviation,
{
++*pp;
if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
- return false;
+ return FALSE;
++c;
continue;
}
/* Look for the ':' that separates the field name from the field
values. Data members are delimited by a single ':', while member
functions are delimited by a pair of ':'s. When we hit the member
- functions (if any), terminate scan loop and return. */
+ functions (if any), terminate scan loop and return. */
p = strchr (p, ':');
if (p == NULL)
{
bad_stab (orig);
- return false;
+ return FALSE;
}
if (p[1] == ':')
if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
staticsp))
- return false;
+ return FALSE;
++c;
}
*retp = fields;
- return true;
+ return TRUE;
}
/* Special GNU C++ name. */
-static boolean
-parse_stab_cpp_abbrev (dhandle, info, pp, retp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- debug_field *retp;
+static bfd_boolean
+parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
+ const char **pp, debug_field *retp)
{
const char *orig;
int cpp_abbrev;
if (**pp != 'v')
{
bad_stab (*pp);
- return false;
+ return FALSE;
}
++*pp;
context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (context == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
switch (cpp_abbrev)
{
typename = debug_get_type_name (dhandle, context);
if (typename == NULL)
{
- warn_stab (orig, "unnamed $vb type");
+ warn_stab (orig, _("unnamed $vb type"));
typename = "FOO";
}
name = concat ("_vb$", typename, (const char *) NULL);
break;
default:
- warn_stab (orig, "unrecognized C++ abbreviation");
+ warn_stab (orig, _("unrecognized C++ abbreviation"));
name = "INVALID_CPLUSPLUS_ABBREV";
break;
}
if (**pp != ':')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
if (**pp != ',')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
- bitpos = parse_number (pp, (boolean *) NULL);
+ bitpos = parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
*retp = debug_make_field (dhandle, name, type, bitpos, 0,
DEBUG_VISIBILITY_PRIVATE);
if (*retp == DEBUG_FIELD_NULL)
- return false;
+ return FALSE;
- return true;
+ return TRUE;
}
/* Parse a single field in a struct or union. */
-static boolean
-parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- const char *p;
- debug_field *retp;
- boolean *staticsp;
+static bfd_boolean
+parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
+ const char **pp, const char *p,
+ debug_field *retp, bfd_boolean *staticsp)
{
const char *orig;
char *name;
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
default:
- warn_stab (orig, "unknown visibility character for field");
+ warn_stab (orig, _("unknown visibility character for field"));
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
}
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (**pp == ':')
{
if (p == NULL)
{
bad_stab (orig);
- return false;
+ return FALSE;
}
varname = savestring (*pp, p - *pp);
*retp = debug_make_static_member (dhandle, name, type, varname,
visibility);
- *staticsp = true;
+ *staticsp = TRUE;
- return true;
+ return TRUE;
}
if (**pp != ',')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
- bitpos = parse_number (pp, (boolean *) NULL);
+ bitpos = parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ',')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
- bitsize = parse_number (pp, (boolean *) NULL);
+ bitsize = parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
*retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility);
- return true;
+ return TRUE;
}
/* Read member function stabs info for C++ classes. The form of each member
$ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
name (such as `+=') and `.' marks the end of the operator name. */
-static boolean
-parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
- PTR dhandle;
- struct stab_handle *info;
- const char *tagname;
- const char **pp;
- const int *typenums;
- debug_method **retp;
+static bfd_boolean
+parse_stab_members (void *dhandle, struct stab_handle *info,
+ const char *tagname, const char **pp,
+ const int *typenums, debug_method **retp)
{
const char *orig;
debug_method *methods;
}
else
{
- /* This is a completely wierd case. In order to stuff in the
+ /* This is a completely weird case. In order to stuff in the
names that might contain colons (the usual name delimiter),
Mike Tiemann defined a different name format which is
signalled if the identifier is "op$". In that case, the
if (*p != '.')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
name = savestring (*pp, p - *pp);
*pp = p + 1;
do
{
debug_type type;
+ bfd_boolean stub;
char *argtypes;
enum debug_visibility visibility;
- boolean constp, volatilep, staticp;
+ bfd_boolean constp, volatilep, staticp;
bfd_vma voffset;
debug_type context;
const char *physname;
- boolean varargs;
+ bfd_boolean varargs;
if (look_ahead_type != DEBUG_TYPE_NULL)
{
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (type == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (**pp != ':')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
}
if (p == NULL)
{
bad_stab (orig);
- return false;
+ return FALSE;
}
+ stub = FALSE;
+ if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
+ && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
+ stub = TRUE;
+
argtypes = savestring (*pp, p - *pp);
*pp = p + 1;
}
++*pp;
- constp = false;
- volatilep = false;
+ constp = FALSE;
+ volatilep = FALSE;
switch (**pp)
{
case 'A':
break;
case 'B':
/* const member function. */
- constp = true;
+ constp = TRUE;
++*pp;
break;
case 'C':
/* volatile member function. */
- volatilep = true;
+ volatilep = TRUE;
++*pp;
break;
case 'D':
/* const volatile member function. */
- constp = true;
- volatilep = true;
+ constp = TRUE;
+ volatilep = TRUE;
++*pp;
break;
case '*':
/* File compiled with g++ version 1; no information. */
break;
default:
- warn_stab (orig, "const/volatile indicator missing");
+ warn_stab (orig, _("const/volatile indicator missing"));
break;
}
- staticp = false;
+ staticp = FALSE;
switch (**pp)
{
case '*':
/* virtual member function, followed by index. The sign
- bit is set to distinguish pointers-to-methods from
- virtual function indicies. Since the array is in
- words, the quantity must be shifted left by 1 on 16
- bit machine, and by 2 on 32 bit machine, forcing the
- sign bit out, and usable as a valid index into the
- array. Remove the sign bit here. */
+ bit is supposedly set to distinguish
+ pointers-to-methods from virtual function indicies. */
++*pp;
- voffset = parse_number (pp, (boolean *) NULL);
+ voffset = parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
++*pp;
voffset &= 0x7fffffff;
- voffset += 2;
if (**pp == ';' || *pp == '\0')
{
/* Figure out from whence this virtual function
came. It may belong to virtual function table of
one of its baseclasses. */
- look_ahead_type = parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL);
- if (**pp == ':')
- {
- /* g++ version 1 overloaded methods. */
- }
- else
- {
- context = look_ahead_type;
- look_ahead_type = DEBUG_TYPE_NULL;
- if (**pp != ';')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
- }
- }
+ look_ahead_type = parse_stab_type (dhandle, info,
+ (const char *) NULL,
+ pp,
+ (debug_type **) NULL);
+ if (**pp == ':')
+ {
+ /* g++ version 1 overloaded methods. */
+ context = DEBUG_TYPE_NULL;
+ }
+ else
+ {
+ context = look_ahead_type;
+ look_ahead_type = DEBUG_TYPE_NULL;
+ if (**pp != ';')
+ {
+ bad_stab (orig);
+ return FALSE;
+ }
+ ++*pp;
+ }
+ }
break;
case '?':
/* static member function. */
++*pp;
- staticp = true;
+ staticp = TRUE;
voffset = 0;
context = DEBUG_TYPE_NULL;
+ if (strncmp (argtypes, name, strlen (name)) != 0)
+ stub = TRUE;
break;
default:
break;
}
- /* If this is a method type which is not a stub--that is,
- the argument types are fully specified--then the argtypes
- string is actually the physical name of the function.
- Otherwise, the argtypes string is the mangled from of the
- argument types, and the physical name of the function,
- and the argument types, must be deduced from it. */
-
- if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
- && debug_get_parameter_types (dhandle, type, &varargs) != NULL)
+ /* If the type is not a stub, then the argtypes string is
+ the physical name of the function. Otherwise the
+ 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
{
class_type = stab_find_type (dhandle, info, typenums);
if (class_type == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
return_type = debug_get_return_type (dhandle, type);
if (return_type == DEBUG_TYPE_NULL)
{
bad_stab (orig);
- return false;
+ return FALSE;
}
type = parse_stab_argtypes (dhandle, info, class_type, name,
tagname, return_type, argtypes,
constp, volatilep, &physname);
if (type == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
}
if (cvars + 1 >= allocvars)
{
allocvars += 10;
variants = ((debug_method_variant *)
- xrealloc ((PTR) variants,
+ xrealloc (variants,
allocvars * sizeof *variants));
}
constp,
volatilep);
if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
- return false;
+ return FALSE;
++cvars;
}
{
alloc += 10;
methods = ((debug_method *)
- xrealloc ((PTR) methods, alloc * sizeof *methods));
+ xrealloc (methods, alloc * sizeof *methods));
}
methods[c] = debug_make_method (dhandle, name, variants);
*retp = methods;
- return true;
+ return TRUE;
}
/* Parse a string representing argument types for a method. Stabs
the tag name. */
static debug_type
-parse_stab_argtypes (dhandle, info, class_type, fieldname, tagname,
- return_type, argtypes, constp, volatilep, pphysname)
- PTR dhandle;
- struct stab_handle *info;
- debug_type class_type;
- const char *fieldname;
- const char *tagname;
- debug_type return_type;
- const char *argtypes;
- boolean constp;
- boolean volatilep;
- const char **pphysname;
+parse_stab_argtypes (void *dhandle, struct stab_handle *info,
+ debug_type class_type, const char *fieldname,
+ const char *tagname, debug_type return_type,
+ const char *argtypes, bfd_boolean constp,
+ bfd_boolean volatilep, const char **pphysname)
{
- boolean is_full_physname_constructor;
- boolean is_constructor;
- boolean is_destructor;
+ bfd_boolean is_full_physname_constructor;
+ bfd_boolean is_constructor;
+ bfd_boolean is_destructor;
+ bfd_boolean is_v3;
debug_type *args;
- boolean varargs;
+ bfd_boolean varargs;
+ unsigned int physname_len = 0;
/* Constructors are sometimes handled specially. */
is_full_physname_constructor = ((argtypes[0] == '_'
&& argtypes[1] == '_'
- && (isdigit ((unsigned char) argtypes[2])
+ && (ISDIGIT (argtypes[2])
|| argtypes[2] == 'Q'
|| argtypes[2] == 't'))
|| strncmp (argtypes, "__ct", 4) == 0);
&& (argtypes[1] == '$' || argtypes[1] == '.')
&& argtypes[2] == '_')
|| strncmp (argtypes, "__dt", 4) == 0);
+ is_v3 = argtypes[0] == '_' && argtypes[1] == 'Z';
- if (is_destructor || is_full_physname_constructor)
+ if (is_destructor || is_full_physname_constructor || is_v3)
*pphysname = argtypes;
else
{
opname = cplus_mangle_opname (fieldname + 3, 0);
if (opname == NULL)
{
- fprintf (stderr, "No mangling for \"%s\"\n", fieldname);
+ fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname);
return DEBUG_TYPE_NULL;
}
mangled_name_len += strlen (opname);
strcpy (physname, fieldname);
}
+ physname_len = strlen (physname);
strcat (physname, buf);
if (tagname != NULL)
strcat (physname, tagname);
*pphysname = physname;
}
- if (*argtypes == '\0')
+ if (*argtypes == '\0' || is_destructor)
{
args = (debug_type *) xmalloc (sizeof *args);
*args = NULL;
return debug_make_method_type (dhandle, return_type, class_type, args,
- false);
+ FALSE);
}
- args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs);
+ args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs, physname_len);
if (args == NULL)
return DEBUG_TYPE_NULL;
This function is called when we have parsed all the method declarations,
so we can look for the vptr base class info. */
-static boolean
-parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- const int *typenums;
- debug_type *retvptrbase;
- boolean *retownvptr;
+static bfd_boolean
+parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
+ const char **pp, const int *typenums,
+ debug_type *retvptrbase, bfd_boolean *retownvptr)
{
const char *orig;
const char *hold;
int vtypenums[2];
*retvptrbase = DEBUG_TYPE_NULL;
- *retownvptr = false;
+ *retownvptr = FALSE;
orig = *pp;
- /* If we are positioned at a ';', then skip it. */
+ /* If we are positioned at a ';', then skip it. */
if (**pp == ';')
++*pp;
if (**pp != '~')
- return true;
+ return TRUE;
++*pp;
if (**pp == '=' || **pp == '+' || **pp == '-')
{
/* Obsolete flags that used to indicate the presence of
- constructors and/or destructors. */
+ constructors and/or destructors. */
++*pp;
}
if (**pp != '%')
- return true;
+ return TRUE;
++*pp;
/* The next number is the type number of the base class (possibly
our own class) which supplies the vtable for this class. */
if (! parse_stab_type_number (pp, vtypenums))
- return false;
+ return FALSE;
if (vtypenums[0] == typenums[0]
&& vtypenums[1] == typenums[1])
- *retownvptr = true;
+ *retownvptr = TRUE;
else
{
debug_type vtype;
if (*p != ';')
{
bad_stab (orig);
- return false;
+ return FALSE;
}
*retvptrbase = vtype;
*pp = p + 1;
}
- return true;
+ return TRUE;
}
/* Read a definition of an array type. */
static debug_type
-parse_stab_array_type (dhandle, info, pp, stringp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- boolean stringp;
+parse_stab_array_type (void *dhandle, struct stab_handle *info,
+ const char **pp, bfd_boolean stringp)
{
const char *orig;
+ const char *p;
+ int typenums[2];
debug_type index_type;
- boolean adjustable;
+ bfd_boolean adjustable;
bfd_signed_vma lower, upper;
debug_type element_type;
/* FIXME: gdb checks os9k_stabs here. */
- index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ /* If the index type is type 0, we take it as int. */
+ p = *pp;
+ if (! parse_stab_type_number (&p, typenums))
+ return DEBUG_TYPE_NULL;
+ if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
+ {
+ index_type = debug_find_named_type (dhandle, "int");
+ if (index_type == DEBUG_TYPE_NULL)
+ {
+ index_type = debug_make_int_type (dhandle, 4, FALSE);
+ if (index_type == DEBUG_TYPE_NULL)
+ return DEBUG_TYPE_NULL;
+ }
+ *pp = p;
+ }
+ else
+ {
+ index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
+ (debug_type **) NULL);
+ }
+
if (**pp != ';')
{
bad_stab (orig);
}
++*pp;
- adjustable = false;
+ adjustable = FALSE;
- if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '-')
{
++*pp;
- adjustable = true;
+ adjustable = TRUE;
}
- lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
- return false;
+ return DEBUG_TYPE_NULL;
}
++*pp;
- if (! isdigit ((unsigned char) **pp) && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '-')
{
++*pp;
- adjustable = true;
+ adjustable = TRUE;
}
- upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
+ upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
if (**pp != ';')
{
bad_stab (orig);
- return false;
+ return DEBUG_TYPE_NULL;
}
++*pp;
element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
(debug_type **) NULL);
if (element_type == DEBUG_TYPE_NULL)
- return false;
+ return DEBUG_TYPE_NULL;
if (adjustable)
{
upper, stringp);
}
-/* Keep a stack of N_BINCL include files. */
+/* This struct holds information about files we have seen using
+ N_BINCL. */
struct bincl_file
{
+ /* The next N_BINCL file. */
struct bincl_file *next;
+ /* The next N_BINCL on the stack. */
+ struct bincl_file *next_stack;
+ /* The file name. */
const char *name;
+ /* The hash value. */
+ bfd_vma hash;
+ /* The file index. */
+ unsigned int file;
+ /* The list of types defined in this file. */
+ struct stab_types *file_types;
};
/* Start a new N_BINCL file, pushing it onto the stack. */
static void
-push_bincl (info, name)
- struct stab_handle *info;
- const char *name;
+push_bincl (struct stab_handle *info, const char *name, bfd_vma hash)
{
struct bincl_file *n;
n = (struct bincl_file *) xmalloc (sizeof *n);
- n->next = info->bincl_stack;
+ n->next = info->bincl_list;
+ n->next_stack = info->bincl_stack;
n->name = name;
+ n->hash = hash;
+ n->file = info->files;
+ n->file_types = NULL;
+ info->bincl_list = n;
info->bincl_stack = n;
++info->files;
info->file_types = ((struct stab_types **)
- xrealloc ((PTR) info->file_types,
+ xrealloc (info->file_types,
(info->files
* sizeof *info->file_types)));
- info->file_types[info->files - 1] = NULL;
+ info->file_types[n->file] = NULL;
}
/* Finish an N_BINCL file, at an N_EINCL, popping the name off the
stack. */
static const char *
-pop_bincl (info)
- struct stab_handle *info;
+pop_bincl (struct stab_handle *info)
{
struct bincl_file *o;
o = info->bincl_stack;
if (o == NULL)
return info->main_filename;
- info->bincl_stack = o->next;
- free (o);
+ info->bincl_stack = o->next_stack;
+
+ o->file_types = info->file_types[o->file];
+
if (info->bincl_stack == NULL)
return info->main_filename;
return info->bincl_stack->name;
}
+/* Handle an N_EXCL: get the types from the corresponding N_BINCL. */
+
+static bfd_boolean
+find_excl (struct stab_handle *info, const char *name, bfd_vma hash)
+{
+ struct bincl_file *l;
+
+ ++info->files;
+ info->file_types = ((struct stab_types **)
+ xrealloc (info->file_types,
+ (info->files
+ * sizeof *info->file_types)));
+
+ for (l = info->bincl_list; l != NULL; l = l->next)
+ if (l->hash == hash && strcmp (l->name, name) == 0)
+ break;
+ if (l == NULL)
+ {
+ warn_stab (name, _("Undefined N_EXCL"));
+ info->file_types[info->files - 1] = NULL;
+ return TRUE;
+ }
+
+ info->file_types[info->files - 1] = l->file_types;
+
+ return TRUE;
+}
+
/* Handle a variable definition. gcc emits variable definitions for a
block before the N_LBRAC, so we must hold onto them until we see
it. The SunPRO compiler emits variable definitions after the
N_LBRAC, so we can call debug_record_variable immediately. */
-static boolean
-stab_record_variable (dhandle, info, name, type, kind, val)
- PTR dhandle;
- struct stab_handle *info;
- const char *name;
- debug_type type;
- enum debug_var_kind kind;
- bfd_vma val;
+static bfd_boolean
+stab_record_variable (void *dhandle, struct stab_handle *info,
+ const char *name, debug_type type,
+ enum debug_var_kind kind, bfd_vma val)
{
struct stab_pending_var *v;
v->val = val;
info->pending = v;
- return true;
+ return TRUE;
}
/* Emit pending variable definitions. This is called after we see the
N_LBRAC that starts the block. */
-static boolean
-stab_emit_pending_vars (dhandle, info)
- PTR dhandle;
- struct stab_handle *info;
+static bfd_boolean
+stab_emit_pending_vars (void *dhandle, struct stab_handle *info)
{
struct stab_pending_var *v;
struct stab_pending_var *next;
if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val))
- return false;
+ return FALSE;
next = v->next;
free (v);
info->pending = NULL;
- return true;
+ return TRUE;
}
/* Find the slot for a type in the database. */
static debug_type *
-stab_find_slot (info, typenums)
- struct stab_handle *info;
- const int *typenums;
+stab_find_slot (struct stab_handle *info, const int *typenums)
{
int filenum;
int index;
if (filenum < 0 || (unsigned int) filenum >= info->files)
{
- fprintf (stderr, "Type file number %d out of range\n", filenum);
+ fprintf (stderr, _("Type file number %d out of range\n"), filenum);
return NULL;
}
if (index < 0)
{
- fprintf (stderr, "Type index number %d out of range\n", index);
+ fprintf (stderr, _("Type index number %d out of range\n"), index);
return NULL;
}
allocated yet, create an indirect type. */
static debug_type
-stab_find_type (dhandle, info, typenums)
- PTR dhandle;
- struct stab_handle *info;
- const int *typenums;
+stab_find_type (void *dhandle, struct stab_handle *info, const int *typenums)
{
debug_type *slot;
/* Record that a given type number refers to a given type. */
-static boolean
-stab_record_type (dhandle, info, typenums, type)
- PTR dhandle;
- struct stab_handle *info;
- const int *typenums;
- debug_type type;
+static bfd_boolean
+stab_record_type (void *dhandle ATTRIBUTE_UNUSED, struct stab_handle *info,
+ const int *typenums, debug_type type)
{
debug_type *slot;
slot = stab_find_slot (info, typenums);
if (slot == NULL)
- return false;
+ return FALSE;
/* gdb appears to ignore type redefinitions, so we do as well. */
*slot = type;
- return true;
+ return TRUE;
}
/* Return an XCOFF builtin type. */
static debug_type
-stab_xcoff_builtin_type (dhandle, info, typenum)
- PTR dhandle;
- struct stab_handle *info;
- int typenum;
+stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
+ int typenum)
{
debug_type rettype;
const char *name;
if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT)
{
- fprintf (stderr, "Unrecognized XCOFF type %d\n", typenum);
+ fprintf (stderr, _("Unrecognized XCOFF type %d\n"), typenum);
return DEBUG_TYPE_NULL;
}
if (info->xcoff_types[-typenum] != NULL)
/* The size of this and all the other types are fixed, defined
by the debugging format. */
name = "int";
- rettype = debug_make_int_type (dhandle, 4, false);
+ rettype = debug_make_int_type (dhandle, 4, FALSE);
break;
case 2:
name = "char";
- rettype = debug_make_int_type (dhandle, 1, false);
+ rettype = debug_make_int_type (dhandle, 1, FALSE);
break;
case 3:
name = "short";
- rettype = debug_make_int_type (dhandle, 2, false);
+ rettype = debug_make_int_type (dhandle, 2, FALSE);
break;
case 4:
name = "long";
- rettype = debug_make_int_type (dhandle, 4, false);
+ rettype = debug_make_int_type (dhandle, 4, FALSE);
break;
case 5:
name = "unsigned char";
- rettype = debug_make_int_type (dhandle, 1, true);
+ rettype = debug_make_int_type (dhandle, 1, TRUE);
break;
case 6:
name = "signed char";
- rettype = debug_make_int_type (dhandle, 1, false);
+ rettype = debug_make_int_type (dhandle, 1, FALSE);
break;
case 7:
name = "unsigned short";
- rettype = debug_make_int_type (dhandle, 2, true);
+ rettype = debug_make_int_type (dhandle, 2, TRUE);
break;
case 8:
name = "unsigned int";
- rettype = debug_make_int_type (dhandle, 4, true);
+ rettype = debug_make_int_type (dhandle, 4, TRUE);
break;
case 9:
name = "unsigned";
- rettype = debug_make_int_type (dhandle, 4, true);
+ rettype = debug_make_int_type (dhandle, 4, TRUE);
case 10:
name = "unsigned long";
- rettype = debug_make_int_type (dhandle, 4, true);
+ rettype = debug_make_int_type (dhandle, 4, TRUE);
break;
case 11:
name = "void";
break;
case 15:
name = "integer";
- rettype = debug_make_int_type (dhandle, 4, false);
+ rettype = debug_make_int_type (dhandle, 4, FALSE);
break;
case 16:
name = "boolean";
case 20:
/* FIXME */
name = "character";
- rettype = debug_make_int_type (dhandle, 1, true);
+ rettype = debug_make_int_type (dhandle, 1, TRUE);
break;
case 21:
name = "logical*1";
break;
case 27:
name = "integer*1";
- rettype = debug_make_int_type (dhandle, 1, false);
+ rettype = debug_make_int_type (dhandle, 1, FALSE);
break;
case 28:
name = "integer*2";
- rettype = debug_make_int_type (dhandle, 2, false);
+ rettype = debug_make_int_type (dhandle, 2, FALSE);
break;
case 29:
name = "integer*4";
- rettype = debug_make_int_type (dhandle, 4, false);
+ rettype = debug_make_int_type (dhandle, 4, FALSE);
break;
case 30:
/* FIXME */
name = "wchar";
- rettype = debug_make_int_type (dhandle, 2, false);
+ rettype = debug_make_int_type (dhandle, 2, FALSE);
break;
case 31:
name = "long long";
- rettype = debug_make_int_type (dhandle, 8, false);
+ rettype = debug_make_int_type (dhandle, 8, FALSE);
break;
case 32:
name = "unsigned long long";
- rettype = debug_make_int_type (dhandle, 8, true);
+ rettype = debug_make_int_type (dhandle, 8, TRUE);
break;
case 33:
name = "logical*8";
break;
case 34:
name = "integer*8";
- rettype = debug_make_int_type (dhandle, 8, false);
+ rettype = debug_make_int_type (dhandle, 8, FALSE);
break;
default:
abort ();
/* Find or create a tagged type. */
static debug_type
-stab_find_tagged_type (dhandle, info, p, len, kind)
- PTR dhandle;
- struct stab_handle *info;
- const char *p;
- int len;
- enum debug_type_kind kind;
+stab_find_tagged_type (void *dhandle, struct stab_handle *info,
+ const char *p, int len, enum debug_type_kind kind)
{
char *name;
debug_type dtype;
struct stab_demangle_info
{
/* The debugging information handle. */
- PTR dhandle;
+ void *dhandle;
/* The stab information handle. */
struct stab_handle *info;
/* The array of arguments we are building. */
debug_type *args;
/* Whether the method takes a variable number of arguments. */
- boolean varargs;
+ bfd_boolean varargs;
/* The array of types we have remembered. */
struct stab_demangle_typestring *typestrings;
/* The number of typestrings. */
unsigned int typestring_alloc;
};
-static void stab_bad_demangle PARAMS ((const char *));
-static unsigned int stab_demangle_count PARAMS ((const char **));
-static boolean stab_demangle_get_count
- PARAMS ((const char **, unsigned int *));
-static boolean stab_demangle_prefix
- PARAMS ((struct stab_demangle_info *, const char **));
-static boolean stab_demangle_function_name
- PARAMS ((struct stab_demangle_info *, const char **, const char *));
-static boolean stab_demangle_signature
- PARAMS ((struct stab_demangle_info *, const char **));
-static boolean stab_demangle_qualified
- PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
-static boolean stab_demangle_template
- PARAMS ((struct stab_demangle_info *, const char **));
-static boolean stab_demangle_class
- PARAMS ((struct stab_demangle_info *, const char **, const char **));
-static boolean stab_demangle_args
- PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
- boolean *));
-static boolean stab_demangle_arg
- PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
- unsigned int *, unsigned int *));
-static boolean stab_demangle_type
- PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
-static boolean stab_demangle_fund_type
- PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
-static boolean stab_demangle_remember_type
- PARAMS ((struct stab_demangle_info *, const char *, int));
+static void stab_bad_demangle (const char *);
+static unsigned int stab_demangle_count (const char **);
+static bfd_boolean stab_demangle_get_count (const char **, unsigned int *);
+static bfd_boolean stab_demangle_prefix
+ (struct stab_demangle_info *, const char **, unsigned int);
+static bfd_boolean stab_demangle_function_name
+ (struct stab_demangle_info *, const char **, const char *);
+static bfd_boolean stab_demangle_signature
+ (struct stab_demangle_info *, const char **);
+static bfd_boolean stab_demangle_qualified
+ (struct stab_demangle_info *, const char **, debug_type *);
+static bfd_boolean stab_demangle_template
+ (struct stab_demangle_info *, const char **, char **);
+static bfd_boolean stab_demangle_class
+ (struct stab_demangle_info *, const char **, const char **);
+static bfd_boolean stab_demangle_args
+ (struct stab_demangle_info *, const char **, debug_type **, bfd_boolean *);
+static bfd_boolean stab_demangle_arg
+ (struct stab_demangle_info *, const char **, debug_type **,
+ unsigned int *, unsigned int *);
+static bfd_boolean stab_demangle_type
+ (struct stab_demangle_info *, const char **, debug_type *);
+static bfd_boolean stab_demangle_fund_type
+ (struct stab_demangle_info *, const char **, debug_type *);
+static bfd_boolean stab_demangle_remember_type
+ (struct stab_demangle_info *, const char *, int);
/* Warn about a bad demangling. */
static void
-stab_bad_demangle (s)
- const char *s;
+stab_bad_demangle (const char *s)
{
- fprintf (stderr, "bad mangled name `%s'\n", s);
+ fprintf (stderr, _("bad mangled name `%s'\n"), s);
}
/* Get a count from a stab string. */
static unsigned int
-stab_demangle_count (pp)
- const char **pp;
+stab_demangle_count (const char **pp)
{
unsigned int count;
count = 0;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
{
count *= 10;
count += **pp - '0';
/* Require a count in a string. The count may be multiple digits, in
which case it must end in an underscore. */
-static boolean
-stab_demangle_get_count (pp, pi)
- const char **pp;
- unsigned int *pi;
+static bfd_boolean
+stab_demangle_get_count (const char **pp, unsigned int *pi)
{
- if (! isdigit ((unsigned char) **pp))
- return false;
+ if (! ISDIGIT (**pp))
+ return FALSE;
*pi = **pp - '0';
++*pp;
- if (isdigit ((unsigned char) **pp))
+ if (ISDIGIT (**pp))
{
unsigned int count;
const char *p;
count += *p - '0';
++p;
}
- while (isdigit ((unsigned char) *p));
+ while (ISDIGIT (*p));
if (*p == '_')
{
*pp = p + 1;
}
}
- return true;
+ return TRUE;
}
/* This function demangles a physical name, returning a NULL
terminated array of argument types. */
static debug_type *
-stab_demangle_argtypes (dhandle, info, physname, pvarargs)
- PTR dhandle;
- struct stab_handle *info;
- const char *physname;
- boolean *pvarargs;
+stab_demangle_argtypes (void *dhandle, struct stab_handle *info,
+ const char *physname, bfd_boolean *pvarargs,
+ unsigned int physname_len)
{
struct stab_demangle_info minfo;
+ /* Check for the g++ V3 ABI. */
+ if (physname[0] == '_' && physname[1] == 'Z')
+ return stab_demangle_v3_argtypes (dhandle, info, physname, pvarargs);
+
minfo.dhandle = dhandle;
minfo.info = info;
minfo.args = NULL;
- minfo.varargs = false;
+ minfo.varargs = FALSE;
minfo.typestring_alloc = 10;
minfo.typestrings = ((struct stab_demangle_typestring *)
xmalloc (minfo.typestring_alloc
/* cplus_demangle checks for special GNU mangled forms, but we can't
see any of them in mangled method argument types. */
- if (! stab_demangle_prefix (&minfo, &physname))
+ if (! stab_demangle_prefix (&minfo, &physname, physname_len))
goto error_return;
if (*physname != '\0')
minfo.typestrings = NULL;
if (minfo.args == NULL)
- fprintf (stderr, "no argument types in mangled string\n");
+ fprintf (stderr, _("no argument types in mangled string\n"));
*pvarargs = minfo.varargs;
return minfo.args;
/* Demangle the prefix of the mangled name. */
-static boolean
-stab_demangle_prefix (minfo, pp)
- struct stab_demangle_info *minfo;
- const char **pp;
+static bfd_boolean
+stab_demangle_prefix (struct stab_demangle_info *minfo, const char **pp,
+ unsigned int physname_len)
{
const char *scan;
unsigned int i;
/* cplus_demangle checks for global constructors and destructors,
but we can't see them in mangled argument types. */
- /* Look for `__'. */
- scan = *pp;
- do
+ if (physname_len)
+ scan = *pp + physname_len;
+ else
{
- scan = strchr (scan, '_');
- }
- while (scan != NULL && *++scan != '_');
+ /* Look for `__'. */
+ scan = *pp;
+ do
+ scan = strchr (scan, '_');
+ while (scan != NULL && *++scan != '_');
- if (scan == NULL)
- {
- stab_bad_demangle (*pp);
- return false;
- }
+ if (scan == NULL)
+ {
+ stab_bad_demangle (*pp);
+ return FALSE;
+ }
- --scan;
+ --scan;
- /* We found `__'; move ahead to the last contiguous `__' pair. */
- i = strspn (scan, "_");
- if (i > 2)
- scan += i - 2;
+ /* We found `__'; move ahead to the last contiguous `__' pair. */
+ i = strspn (scan, "_");
+ if (i > 2)
+ scan += i - 2;
+ }
if (scan == *pp
- && (isdigit ((unsigned char) scan[2])
+ && (ISDIGIT (scan[2])
|| scan[2] == 'Q'
|| scan[2] == 't'))
{
/* This is a GNU style constructor name. */
*pp = scan + 2;
- return true;
+ return TRUE;
}
else if (scan == *pp
- && ! isdigit ((unsigned char) scan[2])
+ && ! ISDIGIT (scan[2])
&& scan[2] != 't')
{
/* Look for the `__' that separates the prefix from the
if (scan == NULL || scan[2] == '\0')
{
stab_bad_demangle (*pp);
- return false;
+ return FALSE;
}
return stab_demangle_function_name (minfo, pp, scan);
else
{
stab_bad_demangle (*pp);
- return false;
+ return FALSE;
}
/*NOTREACHED*/
}
double underscore which separates the function name from the
signature. */
-static boolean
-stab_demangle_function_name (minfo, pp, scan)
- struct stab_demangle_info *minfo;
- const char **pp;
- const char *scan;
+static bfd_boolean
+stab_demangle_function_name (struct stab_demangle_info *minfo,
+ const char **pp, const char *scan)
{
const char *name;
/* This is a type conversion operator. */
tem = name + 5;
if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
- return false;
+ return FALSE;
}
else if (name[0] == '_'
&& name[1] == '_'
/* This is a type conversion operator. */
tem = name + 4;
if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
- return false;
+ return FALSE;
}
- return true;
+ return TRUE;
}
/* Demangle the signature. This is where the argument types are
found. */
-static boolean
-stab_demangle_signature (minfo, pp)
- struct stab_demangle_info *minfo;
- const char **pp;
+static bfd_boolean
+stab_demangle_signature (struct stab_demangle_info *minfo, const char **pp)
{
const char *orig;
- boolean expect_func, func_done;
+ bfd_boolean expect_func, func_done;
const char *hold;
orig = *pp;
- expect_func = false;
- func_done = false;
+ expect_func = FALSE;
+ func_done = FALSE;
hold = NULL;
while (**pp != '\0')
hold = *pp;
if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL)
|| ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return false;
- expect_func = true;
+ return FALSE;
+ expect_func = TRUE;
hold = NULL;
break;
hold = *pp;
if (! stab_demangle_class (minfo, pp, (const char **) NULL)
|| ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return false;
- expect_func = true;
+ return FALSE;
+ expect_func = TRUE;
hold = NULL;
break;
/* Function. I don't know if this actually happens with g++
output. */
hold = NULL;
- func_done = true;
+ func_done = TRUE;
++*pp;
if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return false;
+ return FALSE;
break;
case 't':
/* Template. */
if (hold == NULL)
hold = *pp;
- if (! stab_demangle_template (minfo, pp)
+ if (! stab_demangle_template (minfo, pp, (char **) NULL)
|| ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return false;
+ return FALSE;
hold = NULL;
- expect_func = true;
+ expect_func = TRUE;
break;
case '_':
has been mangled by some algorithm we don't know how to
deal with. So just reject the entire demangling. */
stab_bad_demangle (orig);
- return false;
+ return FALSE;
default:
/* Assume we have stumbled onto the first outermost function
argument token, and start processing args. */
- func_done = true;
+ func_done = TRUE;
if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return false;
+ return FALSE;
break;
}
if (expect_func)
{
- func_done = true;
+ func_done = TRUE;
if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return false;
+ return FALSE;
}
}
first case, and need to ensure that the '(void)' gets added
to the current declp. */
if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return false;
+ return FALSE;
}
- return true;
+ return TRUE;
}
/* Demangle a qualified name, such as "Q25Outer5Inner" which is the
mangled form of "Outer::Inner". */
-static boolean
-stab_demangle_qualified (minfo, pp, ptype)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type *ptype;
+static bfd_boolean
+stab_demangle_qualified (struct stab_demangle_info *minfo, const char **pp,
+ debug_type *ptype)
{
const char *orig;
const char *p;
preceded by an underscore (to distinguish it from the <= 9
case) and followed by an underscore. */
p = *pp + 2;
- if (! isdigit ((unsigned char) *p) || *p == '0')
+ if (! ISDIGIT (*p) || *p == '0')
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
qualifiers = atoi (p);
- while (isdigit ((unsigned char) *p))
+ while (ISDIGIT (*p))
++p;
if (*p != '_')
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
*pp = p + 1;
break;
case '0':
default:
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
context = DEBUG_TYPE_NULL;
++*pp;
if (**pp == 't')
{
- /* FIXME: I don't know how to handle the ptype != NULL case
- here. */
- if (! stab_demangle_template (minfo, pp))
- return false;
+ char *name;
+
+ if (! stab_demangle_template (minfo, pp,
+ ptype != NULL ? &name : NULL))
+ return FALSE;
+
+ if (ptype != NULL)
+ {
+ context = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ name, strlen (name),
+ DEBUG_KIND_CLASS);
+ free (name);
+ if (context == DEBUG_TYPE_NULL)
+ return FALSE;
+ }
}
else
{
if (strlen (*pp) < len)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
if (ptype != NULL)
ft = debug_get_field_type (minfo->dhandle, *fields);
if (ft == NULL)
- return false;
+ return FALSE;
dn = debug_get_type_name (minfo->dhandle, ft);
if (dn != NULL && strcmp (dn, name) == 0)
{
if (context == DEBUG_TYPE_NULL)
{
- /* We have to fall back on finding the type by name.
+ /* We have to fall back on finding the type by name.
If there are more types to come, then this must
be a class. Otherwise, it could be anything. */
? DEBUG_KIND_ILLEGAL
: DEBUG_KIND_CLASS));
if (context == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
}
}
}
if (ptype != NULL)
*ptype = context;
- return true;
+ return TRUE;
}
-/* Demangle a template. */
+/* Demangle a template. If PNAME is not NULL, this sets *PNAME to a
+ string representation of the template. */
-static boolean
-stab_demangle_template (minfo, pp)
- struct stab_demangle_info *minfo;
- const char **pp;
+static bfd_boolean
+stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
+ char **pname)
{
const char *orig;
unsigned int r, i;
if (r == 0 || strlen (*pp) < r)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
*pp += r;
if (stab_demangle_get_count (pp, &r) == 0)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
for (i = 0; i < r; i++)
/* This is a type parameter. */
++*pp;
if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
- return false;
+ return FALSE;
}
else
{
const char *old_p;
- boolean pointerp, realp, integralp, charp, boolp;
- boolean done;
+ bfd_boolean pointerp, realp, integralp, charp, boolp;
+ bfd_boolean done;
old_p = *pp;
- pointerp = false;
- realp = false;
- integralp = false;
- charp = false;
- boolp = false;
- done = false;
+ pointerp = FALSE;
+ realp = FALSE;
+ integralp = FALSE;
+ charp = FALSE;
+ boolp = FALSE;
+ done = FALSE;
/* This is a value parameter. */
if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
- return false;
+ return FALSE;
while (*old_p != '\0' && ! done)
{
case 'P':
case 'p':
case 'R':
- pointerp = true;
- done = true;
+ pointerp = TRUE;
+ done = TRUE;
break;
case 'C': /* Const. */
case 'S': /* Signed. */
++old_p;
break;
case 'Q': /* Qualified name. */
- integralp = true;
- done = true;
+ integralp = TRUE;
+ done = TRUE;
break;
case 'T': /* Remembered type. */
abort ();
case 'i': /* Int. */
case 's': /* Short. */
case 'w': /* Wchar_t. */
- integralp = true;
- done = true;
+ integralp = TRUE;
+ done = TRUE;
break;
case 'b': /* Bool. */
- boolp = true;
- done = true;
+ boolp = TRUE;
+ done = TRUE;
break;
case 'c': /* Char. */
- charp = true;
- done = true;
+ charp = TRUE;
+ done = TRUE;
break;
case 'r': /* Long double. */
case 'd': /* Double. */
case 'f': /* Float. */
- realp = true;
- done = true;
+ realp = TRUE;
+ done = TRUE;
break;
default:
- /* Assume it's a uder defined integral type. */
- integralp = true;
- done = true;
+ /* Assume it's a user defined integral type. */
+ integralp = TRUE;
+ done = TRUE;
break;
}
}
{
if (**pp == 'm')
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
}
else if (charp)
if (val == 0)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
}
else if (boolp)
if (val != 0 && val != 1)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
}
else if (realp)
{
if (**pp == 'm')
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
if (**pp == '.')
{
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
}
if (**pp == 'e')
{
++*pp;
- while (isdigit ((unsigned char) **pp))
+ while (ISDIGIT (**pp))
++*pp;
}
}
{
unsigned int len;
- if (! stab_demangle_get_count (pp, &len))
+ len = stab_demangle_count (pp);
+ if (len == 0)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
*pp += len;
}
}
}
- return true;
+ /* We can translate this to a string fairly easily by invoking the
+ regular demangling routine. */
+ if (pname != NULL)
+ {
+ char *s1, *s2, *s3, *s4 = NULL;
+ char *from, *to;
+
+ s1 = savestring (orig, *pp - orig);
+
+ s2 = concat ("NoSuchStrinG__", s1, (const char *) NULL);
+
+ free (s1);
+
+ s3 = cplus_demangle (s2, DMGL_ANSI);
+
+ free (s2);
+
+ if (s3 != NULL)
+ s4 = strstr (s3, "::NoSuchStrinG");
+ if (s3 == NULL || s4 == NULL)
+ {
+ stab_bad_demangle (orig);
+ if (s3 != NULL)
+ free (s3);
+ return FALSE;
+ }
+
+ /* Eliminating all spaces, except those between > characters,
+ makes it more likely that the demangled name will match the
+ name which g++ used as the structure name. */
+ for (from = to = s3; from != s4; ++from)
+ if (*from != ' '
+ || (from[1] == '>' && from > s3 && from[-1] == '>'))
+ *to++ = *from;
+
+ *pname = savestring (s3, to - s3);
+
+ free (s3);
+ }
+
+ return TRUE;
}
/* Demangle a class name. */
-static boolean
-stab_demangle_class (minfo, pp, pstart)
- struct stab_demangle_info *minfo;
- const char **pp;
- const char **pstart;
+static bfd_boolean
+stab_demangle_class (struct stab_demangle_info *minfo ATTRIBUTE_UNUSED,
+ const char **pp, const char **pstart)
{
const char *orig;
unsigned int n;
if (strlen (*pp) < n)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
if (pstart != NULL)
*pp += n;
- return true;
+ return TRUE;
}
/* Demangle function arguments. If the pargs argument is not NULL, it
is set to a NULL terminated array holding the arguments. */
-static boolean
-stab_demangle_args (minfo, pp, pargs, pvarargs)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type **pargs;
- boolean *pvarargs;
+static bfd_boolean
+stab_demangle_args (struct stab_demangle_info *minfo, const char **pp,
+ debug_type **pargs, bfd_boolean *pvarargs)
{
const char *orig;
unsigned int alloc, count;
if (pargs != NULL)
{
*pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
- *pvarargs = false;
+ *pvarargs = FALSE;
}
count = 0;
if (! stab_demangle_get_count (pp, &r))
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
}
if (! stab_demangle_get_count (pp, &t))
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
if (t >= minfo->typestring_count)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
while (r-- > 0)
{
tem = minfo->typestrings[t].typestring;
if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc))
- return false;
+ return FALSE;
}
}
else
{
if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc))
- return false;
+ return FALSE;
}
}
if (**pp == 'e')
{
if (pargs != NULL)
- *pvarargs = true;
+ *pvarargs = TRUE;
++*pp;
}
- return true;
+ return TRUE;
}
/* Demangle a single argument. */
-static boolean
-stab_demangle_arg (minfo, pp, pargs, pcount, palloc)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type **pargs;
- unsigned int *pcount;
- unsigned int *palloc;
+static bfd_boolean
+stab_demangle_arg (struct stab_demangle_info *minfo, const char **pp,
+ debug_type **pargs, unsigned int *pcount,
+ unsigned int *palloc)
{
const char *start;
debug_type type;
if (! stab_demangle_type (minfo, pp,
pargs == NULL ? (debug_type *) NULL : &type)
|| ! stab_demangle_remember_type (minfo, start, *pp - start))
- return false;
+ return FALSE;
if (pargs != NULL)
{
if (type == DEBUG_TYPE_NULL)
- return false;
+ return FALSE;
if (*pcount + 1 >= *palloc)
{
++*pcount;
}
- return true;
+ return TRUE;
}
/* Demangle a type. If the ptype argument is not NULL, *ptype is set
to the newly allocated type. */
-static boolean
-stab_demangle_type (minfo, pp, ptype)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type *ptype;
+static bfd_boolean
+stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
+ debug_type *ptype)
{
const char *orig;
/* A pointer type. */
++*pp;
if (! stab_demangle_type (minfo, pp, ptype))
- return false;
+ return FALSE;
if (ptype != NULL)
*ptype = debug_make_pointer_type (minfo->dhandle, *ptype);
break;
/* A reference type. */
++*pp;
if (! stab_demangle_type (minfo, pp, ptype))
- return false;
+ return FALSE;
if (ptype != NULL)
*ptype = debug_make_reference_type (minfo->dhandle, *ptype);
break;
high = 0;
while (**pp != '\0' && **pp != '_')
{
- if (! isdigit ((unsigned char) **pp))
+ if (! ISDIGIT (**pp))
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
high *= 10;
high += **pp - '0';
if (**pp != '_')
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
++*pp;
if (! stab_demangle_type (minfo, pp, ptype))
- return false;
+ return FALSE;
if (ptype != NULL)
{
debug_type int_type;
int_type = debug_find_named_type (minfo->dhandle, "int");
if (int_type == NULL)
- int_type = debug_make_int_type (minfo->dhandle, 4, false);
+ int_type = debug_make_int_type (minfo->dhandle, 4, FALSE);
*ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type,
- 0, high, false);
+ 0, high, FALSE);
}
}
break;
if (! stab_demangle_get_count (pp, &i))
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
if (i >= minfo->typestring_count)
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
p = minfo->typestrings[i].typestring;
if (! stab_demangle_type (minfo, &p, ptype))
- return false;
+ return FALSE;
}
break;
/* A function. */
{
debug_type *args;
- boolean varargs;
+ bfd_boolean varargs;
++*pp;
if (! stab_demangle_args (minfo, pp,
? (debug_type **) NULL
: &args),
(ptype == NULL
- ? (boolean *) NULL
+ ? (bfd_boolean *) NULL
: &varargs)))
- return false;
+ return FALSE;
if (**pp != '_')
{
/* cplus_demangle will accept a function without a return
type, but I don't know when that will happen, or what
to do if it does. */
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
++*pp;
if (! stab_demangle_type (minfo, pp, ptype))
- return false;
+ return FALSE;
if (ptype != NULL)
*ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
varargs);
case 'M':
case 'O':
{
- boolean memberp, constp, volatilep;
+ bfd_boolean memberp, constp, volatilep;
+ debug_type class_type = DEBUG_TYPE_NULL;
debug_type *args;
- boolean varargs;
+ bfd_boolean varargs;
unsigned int n;
const char *name;
memberp = **pp == 'M';
- constp = false;
- volatilep = false;
+ constp = FALSE;
+ volatilep = FALSE;
args = NULL;
- varargs = false;
+ varargs = FALSE;
++*pp;
- if (! isdigit ((unsigned char) **pp))
+ if (ISDIGIT (**pp))
{
- stab_bad_demangle (orig);
- return false;
+ n = stab_demangle_count (pp);
+ if (strlen (*pp) < n)
+ {
+ stab_bad_demangle (orig);
+ return FALSE;
+ }
+ name = *pp;
+ *pp += n;
+
+ if (ptype != NULL)
+ {
+ class_type = stab_find_tagged_type (minfo->dhandle,
+ minfo->info,
+ name, (int) n,
+ DEBUG_KIND_CLASS);
+ if (class_type == DEBUG_TYPE_NULL)
+ return FALSE;
+ }
+ }
+ else if (**pp == 'Q')
+ {
+ if (! stab_demangle_qualified (minfo, pp,
+ (ptype == NULL
+ ? (debug_type *) NULL
+ : &class_type)))
+ return FALSE;
}
- n = stab_demangle_count (pp);
- if (strlen (*pp) < n)
+ else
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
- name = *pp;
- *pp += n;
if (memberp)
{
if (**pp == 'C')
{
- constp = true;
+ constp = TRUE;
++*pp;
}
else if (**pp == 'V')
{
- volatilep = true;
+ volatilep = TRUE;
++*pp;
}
if (**pp != 'F')
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
++*pp;
if (! stab_demangle_args (minfo, pp,
? (debug_type **) NULL
: &args),
(ptype == NULL
- ? (boolean *) NULL
+ ? (bfd_boolean *) NULL
: &varargs)))
- return false;
+ return FALSE;
}
if (**pp != '_')
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
++*pp;
if (! stab_demangle_type (minfo, pp, ptype))
- return false;
+ return FALSE;
if (ptype != NULL)
{
- debug_type class_type;
-
- class_type = stab_find_tagged_type (minfo->dhandle, minfo->info,
- name, (int) n,
- DEBUG_KIND_CLASS);
- if (class_type == DEBUG_TYPE_NULL)
- return false;
-
if (! memberp)
*ptype = debug_make_offset_type (minfo->dhandle, class_type,
*ptype);
case 'G':
++*pp;
if (! stab_demangle_type (minfo, pp, ptype))
- return false;
+ return FALSE;
break;
case 'C':
++*pp;
if (! stab_demangle_type (minfo, pp, ptype))
- return false;
+ return FALSE;
if (ptype != NULL)
*ptype = debug_make_const_type (minfo->dhandle, *ptype);
break;
hold = *pp;
if (! stab_demangle_qualified (minfo, pp, ptype))
- return false;
+ return FALSE;
}
break;
default:
if (! stab_demangle_fund_type (minfo, pp, ptype))
- return false;
+ return FALSE;
break;
}
- return true;
+ return TRUE;
}
/* Demangle a fundamental type. If the ptype argument is not NULL,
*ptype is set to the newly allocated type. */
-static boolean
-stab_demangle_fund_type (minfo, pp, ptype)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type *ptype;
+static bfd_boolean
+stab_demangle_fund_type (struct stab_demangle_info *minfo, const char **pp,
+ debug_type *ptype)
{
const char *orig;
- boolean constp, volatilep, unsignedp, signedp;
- boolean done;
+ bfd_boolean constp, volatilep, unsignedp, signedp;
+ bfd_boolean done;
orig = *pp;
- constp = false;
- volatilep = false;
- unsignedp = false;
- signedp = false;
+ constp = FALSE;
+ volatilep = FALSE;
+ unsignedp = FALSE;
+ signedp = FALSE;
- done = false;
+ done = FALSE;
while (! done)
{
switch (**pp)
{
case 'C':
- constp = true;
+ constp = TRUE;
++*pp;
break;
case 'U':
- unsignedp = true;
+ unsignedp = TRUE;
++*pp;
break;
case 'S':
- signedp = true;
+ signedp = TRUE;
++*pp;
break;
case 'V':
- volatilep = true;
+ volatilep = TRUE;
++*pp;
break;
default:
- done = true;
+ done = TRUE;
break;
}
}
{
*ptype = debug_find_named_type (minfo->dhandle, "__wchar_t");
if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 2, true);
+ *ptype = debug_make_int_type (minfo->dhandle, 2, TRUE);
}
++*pp;
break;
case 'G':
++*pp;
- if (! isdigit ((unsigned char) **pp))
+ if (! ISDIGIT (**pp))
{
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
/* Fall through. */
case '0': case '1': case '2': case '3': case '4':
const char *hold;
if (! stab_demangle_class (minfo, pp, &hold))
- return false;
+ return FALSE;
if (ptype != NULL)
{
char *name;
name = savestring (hold, *pp - hold);
*ptype = debug_find_named_type (minfo->dhandle, name);
+ free (name);
if (*ptype == DEBUG_TYPE_NULL)
{
/* FIXME: It is probably incorrect to assume that
*ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
hold, *pp - hold,
DEBUG_KIND_ILLEGAL);
+ if (*ptype == DEBUG_TYPE_NULL)
+ return FALSE;
}
- free (name);
}
}
break;
case 't':
- if (! stab_demangle_template (minfo, pp))
- return false;
- abort ();
+ {
+ char *name;
+
+ if (! stab_demangle_template (minfo, pp,
+ ptype != NULL ? &name : NULL))
+ return FALSE;
+ if (ptype != NULL)
+ {
+ *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
+ name, strlen (name),
+ DEBUG_KIND_CLASS);
+ free (name);
+ if (*ptype == DEBUG_TYPE_NULL)
+ return FALSE;
+ }
+ }
break;
default:
stab_bad_demangle (orig);
- return false;
+ return FALSE;
}
if (ptype != NULL)
*ptype = debug_make_volatile_type (minfo->dhandle, *ptype);
}
- return true;
+ return TRUE;
}
/* Remember a type string in a demangled string. */
-static boolean
-stab_demangle_remember_type (minfo, p, len)
- struct stab_demangle_info *minfo;
- const char *p;
- int len;
+static bfd_boolean
+stab_demangle_remember_type (struct stab_demangle_info *minfo,
+ const char *p, int len)
{
if (minfo->typestring_count >= minfo->typestring_alloc)
{
minfo->typestrings[minfo->typestring_count].len = (unsigned int) len;
++minfo->typestring_count;
- return true;
+ return TRUE;
+}
+\f
+/* Demangle names encoded using the g++ V3 ABI. The newer versions of
+ g++ which use this ABI do not encode ordinary method argument types
+ in a mangled name; they simply output the argument types. However,
+ for a static method, g++ simply outputs the return type and the
+ physical name. So in that case we need to demangle the name here.
+ Here PHYSNAME is the physical name of the function, and we set the
+ variable pointed at by PVARARGS to indicate whether this function
+ is varargs. This returns NULL, or a NULL terminated array of
+ argument types. */
+
+static debug_type *
+stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
+ const char *physname, bfd_boolean *pvarargs)
+{
+ struct demangle_component *dc;
+ void *mem;
+ debug_type *pargs;
+
+ dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem);
+ if (dc == NULL)
+ {
+ stab_bad_demangle (physname);
+ return NULL;
+ }
+
+ /* We expect to see TYPED_NAME, and the right subtree describes the
+ function type. */
+ if (dc->type != DEMANGLE_COMPONENT_TYPED_NAME
+ || dc->u.s_binary.right->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ {
+ fprintf (stderr, _("Demangled name is not a function\n"));
+ free (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 = arglist;
+ dc != NULL;
+ dc = dc->u.s_binary.right)
+ {
+ debug_type arg;
+ bfd_boolean varargs;
+
+ if (dc->type != DEMANGLE_COMPONENT_ARGLIST)
+ {
+ fprintf (stderr, _("Unexpected type in v3 arglist demangling\n"));
+ free (pargs);
+ return NULL;
+ }
+
+ arg = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
+ NULL, &varargs);
+ if (arg == NULL)
+ {
+ if (varargs)
+ {
+ *pvarargs = TRUE;
+ continue;
+ }
+ free (pargs);
+ return NULL;
+ }
+
+ if (count + 1 >= alloc)
+ {
+ alloc += 10;
+ pargs = (debug_type *) xrealloc (pargs, alloc * sizeof *pargs);
+ }
+
+ pargs[count] = arg;
+ ++count;
+ }
+
+ pargs[count] = DEBUG_TYPE_NULL;
+
+ return pargs;
+}
+
+/* Convert a struct demangle_component tree describing an argument
+ type into a debug_type. */
+
+static debug_type
+stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
+ struct demangle_component *dc, debug_type context,
+ bfd_boolean *pvarargs)
+{
+ debug_type dt;
+
+ if (pvarargs != NULL)
+ *pvarargs = FALSE;
+
+ switch (dc->type)
+ {
+ /* FIXME: These are demangle component types which we probably
+ need to handle one way or another. */
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_JAVA_CLASS:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ case DEMANGLE_COMPONENT_COMPLEX:
+ case DEMANGLE_COMPONENT_IMAGINARY:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE:
+ case DEMANGLE_COMPONENT_ARRAY_TYPE:
+ case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ case DEMANGLE_COMPONENT_ARGLIST:
+ default:
+ fprintf (stderr, _("Unrecognized demangle component %d\n"),
+ (int) dc->type);
+ return NULL;
+
+ case DEMANGLE_COMPONENT_NAME:
+ if (context != NULL)
+ {
+ const debug_field *fields;
+
+ fields = debug_get_fields (dhandle, context);
+ if (fields != NULL)
+ {
+ /* Try to find this type by looking through the context
+ class. */
+ for (; *fields != DEBUG_FIELD_NULL; fields++)
+ {
+ debug_type ft;
+ const char *dn;
+
+ ft = debug_get_field_type (dhandle, *fields);
+ if (ft == NULL)
+ return NULL;
+ dn = debug_get_type_name (dhandle, ft);
+ if (dn != NULL
+ && (int) strlen (dn) == dc->u.s_name.len
+ && strncmp (dn, dc->u.s_name.s, dc->u.s_name.len) == 0)
+ return ft;
+ }
+ }
+ }
+ return stab_find_tagged_type (dhandle, info, dc->u.s_name.s,
+ dc->u.s_name.len, DEBUG_KIND_ILLEGAL);
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ context = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
+ context, NULL);
+ if (context == NULL)
+ return NULL;
+ return stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.right,
+ context, NULL);
+
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ {
+ char *p;
+ size_t alc;
+
+ /* We print this component to get a class name which we can
+ use. FIXME: This probably won't work if the template uses
+ template parameters which refer to an outer template. */
+ p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+ if (p == NULL)
+ {
+ fprintf (stderr, _("Failed to print demangled template\n"));
+ return NULL;
+ }
+ dt = stab_find_tagged_type (dhandle, info, p, strlen (p),
+ DEBUG_KIND_CLASS);
+ free (p);
+ return dt;
+ }
+
+ case DEMANGLE_COMPONENT_SUB_STD:
+ return stab_find_tagged_type (dhandle, info, dc->u.s_string.string,
+ dc->u.s_string.len, DEBUG_KIND_ILLEGAL);
+
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL,
+ NULL);
+ if (dt == NULL)
+ return NULL;
+
+ switch (dc->type)
+ {
+ default:
+ abort ();
+ case DEMANGLE_COMPONENT_RESTRICT:
+ /* FIXME: We have no way to represent restrict. */
+ return dt;
+ case DEMANGLE_COMPONENT_VOLATILE:
+ return debug_make_volatile_type (dhandle, dt);
+ case DEMANGLE_COMPONENT_CONST:
+ return debug_make_const_type (dhandle, dt);
+ case DEMANGLE_COMPONENT_POINTER:
+ return debug_make_pointer_type (dhandle, dt);
+ case DEMANGLE_COMPONENT_REFERENCE:
+ 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;
+ size_t alc;
+ debug_type ret;
+
+ /* We print this component in order to find out the type name.
+ FIXME: Should we instead expose the
+ demangle_builtin_type_info structure? */
+ p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
+ if (p == NULL)
+ {
+ fprintf (stderr, _("Couldn't get demangled builtin type\n"));
+ return NULL;
+ }
+
+ /* The mangling is based on the type, but does not itself
+ indicate what the sizes are. So we have to guess. */
+ if (strcmp (p, "signed char") == 0)
+ ret = debug_make_int_type (dhandle, 1, FALSE);
+ else if (strcmp (p, "bool") == 0)
+ ret = debug_make_bool_type (dhandle, 1);
+ else if (strcmp (p, "char") == 0)
+ ret = debug_make_int_type (dhandle, 1, FALSE);
+ else if (strcmp (p, "double") == 0)
+ ret = debug_make_float_type (dhandle, 8);
+ else if (strcmp (p, "long double") == 0)
+ ret = debug_make_float_type (dhandle, 8);
+ else if (strcmp (p, "float") == 0)
+ ret = debug_make_float_type (dhandle, 4);
+ else if (strcmp (p, "__float128") == 0)
+ ret = debug_make_float_type (dhandle, 16);
+ else if (strcmp (p, "unsigned char") == 0)
+ ret = debug_make_int_type (dhandle, 1, TRUE);
+ else if (strcmp (p, "int") == 0)
+ ret = debug_make_int_type (dhandle, 4, FALSE);
+ else if (strcmp (p, "unsigned int") == 0)
+ ret = debug_make_int_type (dhandle, 4, TRUE);
+ else if (strcmp (p, "long") == 0)
+ ret = debug_make_int_type (dhandle, 4, FALSE);
+ else if (strcmp (p, "unsigned long") == 0)
+ ret = debug_make_int_type (dhandle, 4, TRUE);
+ else if (strcmp (p, "__int128") == 0)
+ ret = debug_make_int_type (dhandle, 16, FALSE);
+ else if (strcmp (p, "unsigned __int128") == 0)
+ ret = debug_make_int_type (dhandle, 16, TRUE);
+ else if (strcmp (p, "short") == 0)
+ ret = debug_make_int_type (dhandle, 2, FALSE);
+ else if (strcmp (p, "unsigned short") == 0)
+ ret = debug_make_int_type (dhandle, 2, TRUE);
+ else if (strcmp (p, "void") == 0)
+ ret = debug_make_void_type (dhandle);
+ else if (strcmp (p, "wchar_t") == 0)
+ ret = debug_make_int_type (dhandle, 4, TRUE);
+ else if (strcmp (p, "long long") == 0)
+ ret = debug_make_int_type (dhandle, 8, FALSE);
+ else if (strcmp (p, "unsigned long long") == 0)
+ ret = debug_make_int_type (dhandle, 8, TRUE);
+ else if (strcmp (p, "...") == 0)
+ {
+ if (pvarargs == NULL)
+ fprintf (stderr, _("Unexpected demangled varargs\n"));
+ else
+ *pvarargs = TRUE;
+ ret = NULL;
+ }
+ else
+ {
+ fprintf (stderr, _("Unrecognized demangled builtin type\n"));
+ ret = NULL;
+ }
+
+ free (p);
+
+ return ret;
+ }
+ }
}