summaryrefslogtreecommitdiffstats
path: root/binutils-2.17/binutils/stabs.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.17/binutils/stabs.c')
-rw-r--r--binutils-2.17/binutils/stabs.c5399
1 files changed, 0 insertions, 5399 deletions
diff --git a/binutils-2.17/binutils/stabs.c b/binutils-2.17/binutils/stabs.c
deleted file mode 100644
index 879a3e2c..00000000
--- a/binutils-2.17/binutils/stabs.c
+++ /dev/null
@@ -1,5399 +0,0 @@
-/* stabs.c -- Parse stabs debugging information
- Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
- Written by Ian Lance Taylor <ian@cygnus.com>.
-
- This file is part of GNU Binutils.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- 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., 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-/* This file contains code which parses stabs debugging information.
- The organization of this code is based on the gdb stabs reading
- code. The job it does is somewhat different, because it is not
- trying to identify the correct address for anything. */
-
-#include <stdio.h>
-
-#include "bfd.h"
-#include "bucomm.h"
-#include "libiberty.h"
-#include "safe-ctype.h"
-#include "demangle.h"
-#include "debug.h"
-#include "budbg.h"
-#include "filenames.h"
-#include "aout/aout64.h"
-#include "aout/stab_gnu.h"
-
-/* The number of predefined XCOFF types. */
-
-#define XCOFF_TYPE_COUNT 34
-
-/* This structure is used as a handle so that the stab parsing doesn't
- need to use any static variables. */
-
-struct stab_handle
-{
- /* 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;
- /* The offset of the start of the function, so that we can handle
- function relative N_LBRAC and N_RBRAC symbols. */
- bfd_vma function_start_offset;
- /* The version number of gcc which compiled the current compilation
- unit, 0 if not compiled by gcc. */
- int gcc_compiled;
- /* Whether an N_OPT symbol was seen that was not generated by gcc,
- so that we can detect the SunPRO compiler. */
- bfd_boolean n_opt_found;
- /* The main file name. */
- char *main_filename;
- /* 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. */
- 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. */
- struct stab_pending_var *pending;
- /* Number of files for which we have types. */
- unsigned int files;
- /* Lists of types per file. */
- struct stab_types **file_types;
- /* Predefined XCOFF types. */
- 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
- definitions seen before the N_LBRAC of a block. */
-
-struct stab_pending_var
-{
- /* Next pending variable definition. */
- struct stab_pending_var *next;
- /* Name. */
- const char *name;
- /* Type. */
- debug_type type;
- /* Kind. */
- enum debug_var_kind kind;
- /* Value. */
- bfd_vma val;
-};
-
-/* A list of these structures is used to hold the types for a single
- file. */
-
-struct stab_types
-{
- /* Next set of slots for this file. */
- struct stab_types *next;
- /* Types indexed by type number. */
-#define STAB_TYPES_SLOTS (16)
- debug_type types[STAB_TYPES_SLOTS];
-};
-
-/* We keep a list of undefined tags that we encounter, so that we can
- fill them in if the tag is later defined. */
-
-struct stab_tag
-{
- /* Next undefined tag. */
- struct stab_tag *next;
- /* Tag name. */
- const char *name;
- /* Type kind. */
- enum debug_type_kind kind;
- /* Slot to hold real type when we discover it. If we don't, we fill
- in an undefined tag type. */
- debug_type slot;
- /* Indirect type we have created to point at slot. */
- debug_type type;
-};
-
-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
- (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
- (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
- (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
- (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
- (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
- (void *, struct stab_handle *, int);
-static debug_type stab_find_tagged_type
- (void *, struct stab_handle *, const char *, int, enum debug_type_kind);
-static debug_type *stab_demangle_argtypes
- (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 (const char *start, int len)
-{
- char *ret;
-
- ret = (char *) xmalloc (len + 1);
- memcpy (ret, start, len);
- ret[len] = '\0';
- return ret;
-}
-
-/* Read a number from a string. */
-
-static bfd_vma
-parse_number (const char **pp, bfd_boolean *poverflow)
-{
- unsigned long ul;
- const char *orig;
-
- if (poverflow != NULL)
- *poverflow = FALSE;
-
- orig = *pp;
-
- errno = 0;
- ul = strtoul (*pp, (char **) pp, 0);
- if (ul + 1 != 0 || errno == 0)
- {
- /* 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;
- bfd_boolean neg;
- int base;
- bfd_vma over, lastdig;
- bfd_boolean overflow;
- bfd_vma v;
-
- /* Our own version of strtoul, for a bfd_vma. */
- p = orig;
-
- neg = FALSE;
- if (*p == '+')
- ++p;
- else if (*p == '-')
- {
- neg = TRUE;
- ++p;
- }
-
- base = 10;
- if (*p == '0')
- {
- if (p[1] == 'x' || p[1] == 'X')
- {
- base = 16;
- p += 2;
- }
- else
- {
- base = 8;
- ++p;
- }
- }
-
- over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
- lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
-
- overflow = FALSE;
- v = 0;
- while (1)
- {
- int d;
-
- d = *p++;
- if (ISDIGIT (d))
- d -= '0';
- else if (ISUPPER (d))
- d -= 'A';
- else if (ISLOWER (d))
- d -= 'a';
- else
- break;
-
- if (d >= base)
- break;
-
- if (v > over || (v == over && (bfd_vma) d > lastdig))
- {
- overflow = TRUE;
- break;
- }
- }
-
- if (! overflow)
- {
- if (neg)
- v = - v;
- return v;
- }
- }
-
- /* If we get here, the number is too large to represent in a
- bfd_vma. */
- if (poverflow != NULL)
- *poverflow = TRUE;
- else
- warn_stab (orig, _("numeric overflow"));
-
- return 0;
-}
-
-/* Give an error for a bad stab string. */
-
-static void
-bad_stab (const char *p)
-{
- fprintf (stderr, _("Bad stab: %s\n"), p);
-}
-
-/* Warn about something in a stab string. */
-
-static void
-warn_stab (const char *p, const char *err)
-{
- fprintf (stderr, _("Warning: %s: %s\n"), err, p);
-}
-
-/* Create a handle to parse stabs symbols with. */
-
-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;
- 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. */
-
-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 (! 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)
- {
- enum debug_type_kind kind;
-
- kind = st->kind;
- if (kind == DEBUG_KIND_ILLEGAL)
- kind = DEBUG_KIND_STRUCT;
- st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
- if (st->slot == DEBUG_TYPE_NULL)
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Handle a single stabs symbol. */
-
-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:
- case N_FN_SEQ:
- break;
-
- case N_LBRAC:
- /* Ignore extra outermost context from SunPRO cc and acc. */
- if (info->n_opt_found && desc == 1)
- break;
-
- if (! info->within_function)
- {
- fprintf (stderr, _("N_LBRAC not within function\n"));
- return FALSE;
- }
-
- /* Start an inner lexical block. */
- if (! debug_start_block (dhandle,
- (value
- + info->file_start_offset
- + info->function_start_offset)))
- return FALSE;
-
- /* Emit any pending variable definitions. */
- if (! stab_emit_pending_vars (dhandle, info))
- return FALSE;
-
- ++info->block_depth;
- break;
-
- case N_RBRAC:
- /* Ignore extra outermost context from SunPRO cc and acc. */
- if (info->n_opt_found && desc == 1)
- break;
-
- /* We shouldn't have any pending variable definitions here, but,
- if we do, we probably need to emit them before closing the
- block. */
- if (! stab_emit_pending_vars (dhandle, info))
- return FALSE;
-
- /* End an inner lexical block. */
- if (! debug_end_block (dhandle,
- (value
- + info->file_start_offset
- + info->function_start_offset)))
- return FALSE;
-
- --info->block_depth;
- if (info->block_depth < 0)
- {
- fprintf (stderr, _("Too many N_RBRACs\n"));
- return FALSE;
- }
- break;
-
- case N_SO:
- /* This always ends a function. */
- if (info->within_function)
- {
- 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;
- }
-
- /* 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
- {
- 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;
- break;
-
- case N_BINCL:
- /* Start an include file which may be replaced. */
- push_bincl (info, string, value);
- if (! debug_start_source (dhandle, string))
- return FALSE;
- break;
-
- case N_EINCL:
- /* End an N_BINCL include. */
- if (! debug_start_source (dhandle, pop_bincl (info)))
- return FALSE;
- break;
-
- case N_EXCL:
- /* This is a duplicate of a header file named by N_BINCL which
- was eliminated by the linker. */
- if (! find_excl (info, string, value))
- return FALSE;
- break;
-
- case N_SLINE:
- if (! debug_record_line (dhandle, desc,
- value + (info->within_function
- ? info->function_start_offset : 0)))
- return FALSE;
- break;
-
- case N_BCOMM:
- if (! debug_start_common_block (dhandle, string))
- return FALSE;
- break;
-
- case N_ECOMM:
- if (! debug_end_common_block (dhandle, string))
- 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;
-
- colon = strchr (string, ':');
- if (colon != NULL
- && (colon[1] == 'f' || colon[1] == 'F'))
- {
- if (info->within_function)
- {
- 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;
- }
-
- if (! parse_stab_string (dhandle, info, type, desc, value, string))
- return FALSE;
- }
- break;
-
- case N_OPT:
- if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
- info->gcc_compiled = 2;
- else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
- info->gcc_compiled = 1;
- else
- info->n_opt_found = TRUE;
- break;
-
- case N_OBJ:
- case N_ENDM:
- case N_MAIN:
- case N_WARNING:
- break;
- }
-
- return TRUE;
-}
-
-/* Parse the stabs 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;
- bfd_boolean synonym;
- bfd_boolean self_crossref;
- unsigned int lineno;
- debug_type *slot;
-
- p = strchr (string, ':');
- if (p == NULL)
- return TRUE;
-
- while (p[1] == ':')
- {
- p += 2;
- p = strchr (p, ':');
- if (p == NULL)
- {
- bad_stab (string);
- return FALSE;
- }
- }
-
- /* GCC 2.x puts the line number in desc. SunOS apparently puts in
- the number of bytes occupied by a type or object, which we
- ignore. */
- if (info->gcc_compiled >= 2)
- lineno = desc;
- else
- lineno = 0;
-
- /* FIXME: Sometimes the special C++ names start with '.'. */
- name = NULL;
- if (string[0] == '$')
- {
- switch (string[1])
- {
- case 't':
- name = "this";
- break;
- case 'v':
- /* Was: name = "vptr"; */
- break;
- case 'e':
- name = "eh_throw";
- break;
- case '_':
- /* This was an anonymous type that was never fixed up. */
- break;
- case 'X':
- /* SunPRO (3.0 at least) static variable encoding. */
- break;
- default:
- warn_stab (string, _("unknown C++ encoded name"));
- break;
- }
- }
-
- if (name == NULL)
- {
- if (p == string || (string[0] == ' ' && p == string + 1))
- name = NULL;
- else
- name = savestring (string, p - string);
- }
-
- ++p;
- if (ISDIGIT (*p) || *p == '(' || *p == '-')
- type = 'l';
- else
- type = *p++;
-
- switch (type)
- {
- case 'c':
- /* c is a special case, not followed by a type-number.
- SYMBOL:c=iVALUE for an integer constant symbol.
- SYMBOL:c=rVALUE for a floating constant symbol.
- SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
- e.g. "b:c=e6,0" for "const b = blob1"
- (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
- if (*p != '=')
- {
- bad_stab (string);
- return FALSE;
- }
- ++p;
- switch (*p++)
- {
- case 'r':
- /* Floating point constant. */
- if (! debug_record_float_const (dhandle, name, atof (p)))
- return FALSE;
- break;
- case 'i':
- /* Integer constant. */
- /* Defining integer constants this way is kind of silly,
- since 'e' constants allows the compiler to give not only
- the value, but the type as well. C has at least int,
- long, unsigned int, and long long as constant types;
- other languages probably should have at least unsigned as
- well as signed constants. */
- if (! debug_record_int_const (dhandle, name, atoi (p)))
- return FALSE;
- break;
- case 'e':
- /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
- can be represented as integral.
- e.g. "b:c=e6,0" for "const b = blob1"
- (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- &p, (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (*p != ',')
- {
- bad_stab (string);
- return FALSE;
- }
- if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
- return FALSE;
- break;
- default:
- bad_stab (string);
- return FALSE;
- }
-
- break;
-
- case 'C':
- /* The name of a caught exception. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- &p, (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_label (dhandle, name, dtype, value))
- return FALSE;
- break;
-
- case 'f':
- case 'F':
- /* A function definition. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
- return FALSE;
-
- /* Sun acc puts declared types of arguments here. We don't care
- about their actual types (FIXME -- we should remember the whole
- function prototype), but the list may define some new types
- that we have to remember, so we must scan it now. */
- while (*p == ';')
- {
- ++p;
- if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL)
- == DEBUG_TYPE_NULL)
- return FALSE;
- }
-
- break;
-
- case 'G':
- {
- 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
- code letter in the dbx data. Dbx data never actually
- contains 'l'. */
- case 'l':
- case 's':
- 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_LOCAL,
- value))
- return FALSE;
- break;
-
- case 'p':
- /* A function parameter. */
- if (*p != 'F')
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- else
- {
- /* pF is a two-letter code that means a function parameter in
- Fortran. The type-number specifies the type of the return
- value. Translate it into a pointer-to-function type. */
- ++p;
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype != DEBUG_TYPE_NULL)
- {
- debug_type ftype;
-
- ftype = debug_make_function_type (dhandle, dtype,
- (debug_type *) NULL, FALSE);
- dtype = debug_make_pointer_type (dhandle, ftype);
- }
- }
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
- value))
- 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 (stabtype == N_FUN)
- {
- /* Prototype of a function referenced by this file. */
- while (*p == ';')
- {
- ++p;
- if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL)
- == DEBUG_TYPE_NULL)
- return FALSE;
- }
- break;
- }
- /* Fall through. */
- case 'R':
- /* Parameter which is in a register. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
- value))
- return FALSE;
- break;
-
- case 'r':
- /* Register variable (either global or local). */
- 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_REGISTER,
- value))
- 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. */
- 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_STATIC,
- value))
- return FALSE;
- break;
-
- case 't':
- /* A typedef. */
- dtype = parse_stab_type (dhandle, info, name, &p, &slot);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (name == NULL)
- {
- /* A nameless type. Nothing to do. */
- return TRUE;
- }
-
- dtype = debug_name_type (dhandle, name, dtype);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
-
- if (slot != NULL)
- *slot = dtype;
-
- break;
-
- case 'T':
- /* Struct, union, or enum tag. For GNU C++, this can be be followed
- 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
- is C++. */
- }
- else
- {
- synonym = TRUE;
- ++p;
- }
-
- dtype = parse_stab_type (dhandle, info, name, &p, &slot);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (name == NULL)
- 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;
- if (slot != NULL)
- *slot = dtype;
-
- /* See if we have a cross reference to this tag which we can now
- 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;
- }
- }
- }
-
- if (synonym)
- {
- dtype = debug_name_type (dhandle, name, dtype);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
-
- if (slot != NULL)
- *slot = dtype;
- }
-
- break;
-
- case 'V':
- /* Static symbol of local scope */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- /* FIXME: gdb checks os9k_stabs here. */
- if (! stab_record_variable (dhandle, info, name, dtype,
- DEBUG_LOCAL_STATIC, value))
- return FALSE;
- break;
-
- case 'v':
- /* Reference parameter. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
- value))
- return FALSE;
- break;
-
- case 'a':
- /* Reference parameter which is in a register. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
- value))
- return FALSE;
- break;
-
- case 'X':
- /* This is used by Sun FORTRAN for "function result value".
- Sun claims ("dbx and dbxtool interfaces", 2nd ed)
- that Pascal uses it too, but when I tried it Pascal used
- "x:3" (local symbol) instead. */
- 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_LOCAL,
- value))
- return FALSE;
- break;
-
- default:
- bad_stab (string);
- return FALSE;
- }
-
- /* FIXME: gdb converts structure values to structure pointers in a
- couple of cases, depending upon the target. */
-
- return TRUE;
-}
-
-/* Parse a stabs type. The typename argument is non-NULL if this is a
- typedef or a tag definition. The pp argument points to the stab
- string, and is updated. The slotp argument points to a place to
- store the slot used if the type is being defined. */
-
-static debug_type
-parse_stab_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, debug_type **slotp)
-{
- const char *orig;
- int typenums[2];
- int size;
- bfd_boolean stringp;
- int descriptor;
- debug_type dtype;
-
- if (slotp != NULL)
- *slotp = NULL;
-
- orig = *pp;
-
- size = -1;
- 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 (**pp) && **pp != '(' && **pp != '-')
- {
- /* 'typenums=' not present, type is anonymous. Read and return
- the definition, but don't put it in the type vector. */
- typenums[0] = typenums[1] = -1;
- }
- else
- {
- if (! parse_stab_type_number (pp, typenums))
- 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);
-
- /* Only set the slot if the type is being defined. This means
- that the mapping from type numbers to types will only record
- the name of the typedef which defines a type. If we don't do
- this, then something like
- typedef int foo;
- int i;
- will record that i is of type foo. Unfortunately, stabs
- information is ambiguous about variable types. For this code,
- typedef int foo;
- int i;
- foo j;
- the stabs information records both i and j as having the same
- type. This could be fixed by patching the compiler. */
- if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0)
- *slotp = stab_find_slot (info, typenums);
-
- /* Type is being defined here. */
- /* Skip the '='. */
- ++*pp;
-
- while (**pp == '@')
- {
- const char *p = *pp + 1;
- const char *attr;
-
- if (ISDIGIT (*p) || *p == '(' || *p == '-')
- /* Member type. */
- break;
-
- /* Type attributes. */
- attr = p;
-
- for (; *p != ';'; ++p)
- {
- if (*p == '\0')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- }
- *pp = p + 1;
-
- switch (*attr)
- {
- 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;
- break;
-
- default:
- /* Ignore unrecognized type attributes, so future
- compilers can invent new ones. */
- break;
- }
- }
- }
-
- descriptor = **pp;
- ++*pp;
-
- switch (descriptor)
- {
- case 'x':
- {
- enum debug_type_kind code;
- const char *q1, *q2, *p;
-
- /* A cross reference to another type. */
- switch (**pp)
- {
- case 's':
- code = DEBUG_KIND_STRUCT;
- break;
- case 'u':
- code = DEBUG_KIND_UNION;
- break;
- case 'e':
- code = DEBUG_KIND_ENUM;
- break;
- default:
- /* Complain and keep going, so compilers can invent new
- cross-reference types. */
- warn_stab (orig, _("unrecognized cross reference type"));
- code = DEBUG_KIND_STRUCT;
- break;
- }
- ++*pp;
-
- q1 = strchr (*pp, '<');
- p = strchr (*pp, ':');
- if (p == NULL)
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- if (q1 != NULL && p > q1 && p[1] == ':')
- {
- 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;
- }
- break;
-
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '(':
- {
- const char *hold;
- int xtypenums[2];
-
- /* This type is defined as another type. */
- (*pp)--;
- hold = *pp;
-
- /* Peek ahead at the number to detect void. */
- if (! parse_stab_type_number (pp, xtypenums))
- return DEBUG_TYPE_NULL;
-
- if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
- {
- /* This type is being defined as itself, which means that
- it is void. */
- dtype = debug_make_void_type (dhandle);
- }
- else
- {
- *pp = hold;
-
- /* Go back to the number and have parse_stab_type get it.
- This means that we can deal with something like
- t(1,2)=(3,4)=... which the Lucid compiler uses. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- }
-
- if (typenums[0] != -1)
- {
- if (! stab_record_type (dhandle, info, typenums, dtype))
- return DEBUG_TYPE_NULL;
- }
-
- break;
- }
-
- case '*':
- dtype = debug_make_pointer_type (dhandle,
- parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL));
- break;
-
- case '&':
- /* Reference to another type. */
- dtype = (debug_make_reference_type
- (dhandle,
- parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL)));
- break;
-
- case 'f':
- /* Function returning another type. */
- /* FIXME: gdb checks os9k_stabs here. */
- dtype = (debug_make_function_type
- (dhandle,
- parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL),
- (debug_type *) NULL, FALSE));
- break;
-
- case 'k':
- /* Const qualifier on some type (Sun). */
- /* FIXME: gdb accepts 'c' here if os9k_stabs. */
- dtype = debug_make_const_type (dhandle,
- parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL));
- break;
-
- case 'B':
- /* Volatile qual on some type (Sun). */
- /* FIXME: gdb accepts 'i' here if os9k_stabs. */
- dtype = (debug_make_volatile_type
- (dhandle,
- parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL)));
- break;
-
- case '@':
- /* Offset (class & variable) type. This is used for a pointer
- relative to an object. */
- {
- debug_type domain;
- debug_type memtype;
-
- /* Member type. */
-
- domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (domain == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
-
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (memtype == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
-
- dtype = debug_make_offset_type (dhandle, domain, memtype);
- }
- break;
-
- case '#':
- /* Method (class & fn) type. */
- if (**pp == '#')
- {
- debug_type return_type;
-
- ++*pp;
- return_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (return_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- dtype = debug_make_method_type (dhandle, return_type,
- DEBUG_TYPE_NULL,
- (debug_type *) NULL, FALSE);
- }
- else
- {
- debug_type domain;
- debug_type return_type;
- debug_type *args;
- unsigned int n;
- unsigned int alloc;
- bfd_boolean varargs;
-
- domain = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (domain == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
-
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- return_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (return_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
-
- alloc = 10;
- args = (debug_type *) xmalloc (alloc * sizeof *args);
- n = 0;
- while (**pp != ';')
- {
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- if (n + 1 >= alloc)
- {
- alloc += 10;
- args = ((debug_type *)
- xrealloc (args, alloc * sizeof *args));
- }
-
- args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (args[n] == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- ++n;
- }
- ++*pp;
-
- /* If the last type is not void, then this function takes a
- variable number of arguments. Otherwise, we must strip
- the void type. */
- if (n == 0
- || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
- varargs = TRUE;
- else
- {
- --n;
- varargs = FALSE;
- }
-
- args[n] = DEBUG_TYPE_NULL;
-
- dtype = debug_make_method_type (dhandle, return_type, domain, args,
- varargs);
- }
- break;
-
- case 'r':
- /* Range type. */
- dtype = parse_stab_range_type (dhandle, info, typename, pp, typenums);
- break;
-
- case 'b':
- /* FIXME: gdb checks os9k_stabs here. */
- /* Sun ACC builtin int type. */
- dtype = parse_stab_sun_builtin_type (dhandle, pp);
- break;
-
- case 'R':
- /* Sun ACC builtin float type. */
- dtype = parse_stab_sun_floating_type (dhandle, pp);
- break;
-
- case 'e':
- /* Enumeration type. */
- dtype = parse_stab_enum_type (dhandle, pp);
- break;
-
- case 's':
- case 'u':
- /* Struct or union type. */
- dtype = parse_stab_struct_type (dhandle, info, typename, pp,
- descriptor == 's', typenums);
- break;
-
- case 'a':
- /* Array type. */
- if (**pp != 'r')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- dtype = parse_stab_array_type (dhandle, info, pp, stringp);
- break;
-
- case 'S':
- dtype = debug_make_set_type (dhandle,
- parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL),
- stringp);
- break;
-
- default:
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
-
- if (dtype == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
-
- if (typenums[0] != -1)
- {
- if (! stab_record_type (dhandle, info, typenums, dtype))
- return DEBUG_TYPE_NULL;
- }
-
- if (size != -1)
- {
- if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
- return DEBUG_TYPE_NULL;
- }
-
- return dtype;
-}
-
-/* Read a number by which a type is referred to in dbx data, or
- perhaps read a pair (FILENUM, TYPENUM) in parentheses. Just a
- single number N is equivalent to (0,N). Return the two numbers by
- storing them in the vector TYPENUMS. */
-
-static bfd_boolean
-parse_stab_type_number (const char **pp, int *typenums)
-{
- const char *orig;
-
- orig = *pp;
-
- if (**pp != '(')
- {
- typenums[0] = 0;
- typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
- }
- else
- {
- ++*pp;
- typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ')')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- }
-
- return TRUE;
-}
-
-/* Parse a range type. */
-
-static debug_type
-parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *typename, const char **pp, const int *typenums)
-{
- const char *orig;
- int rangenums[2];
- bfd_boolean self_subrange;
- debug_type index_type;
- const char *s2, *s3;
- bfd_signed_vma n2, n3;
- bfd_boolean ov2, ov3;
-
- orig = *pp;
-
- index_type = DEBUG_TYPE_NULL;
-
- /* First comes a type we are a subrange of.
- In C it is usually 0, 1 or the type being defined. */
- if (! parse_stab_type_number (pp, rangenums))
- return DEBUG_TYPE_NULL;
-
- self_subrange = (rangenums[0] == typenums[0]
- && rangenums[1] == typenums[1]);
-
- if (**pp == '=')
- {
- *pp = orig;
- index_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (index_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- }
-
- if (**pp == ';')
- ++*pp;
-
- /* The remaining two operands are usually lower and upper bounds of
- the range. But in some special cases they mean something else. */
- s2 = *pp;
- n2 = parse_number (pp, &ov2);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- s3 = *pp;
- n3 = parse_number (pp, &ov3);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- if (ov2 || ov3)
- {
- /* 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 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);
- if (! ov2
- && n2 == 0
- && strncmp (s3, ULLHIGH, sizeof ULLHIGH - 1) == 0)
- return debug_make_int_type (dhandle, 8, TRUE);
- }
-
- warn_stab (orig, _("numeric overflow"));
- }
-
- if (index_type == DEBUG_TYPE_NULL)
- {
- /* A type defined as a subrange of itself, with both bounds 0,
- is void. */
- 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)
- return debug_make_float_type (dhandle, n2);
-
- /* If the upper bound is -1, this is an unsigned int. */
- if (n2 == 0 && n3 == -1)
- {
- /* When gcc is used with -gstabs, but not -gstabs+, it will emit
- long long int:t6=r1;0;-1;
- long long unsigned int:t7=r1;0;-1;
- We hack here to handle this reasonably. */
- if (typename != NULL)
- {
- if (strcmp (typename, "long long int") == 0)
- 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);
- }
- /* FIXME: The size here really depends upon the target. */
- 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);
-
- /* FIXME: gdb checks for the language CHILL here. */
-
- if (n2 == 0)
- {
- if (n3 < 0)
- return debug_make_int_type (dhandle, - n3, TRUE);
- else if (n3 == 0xff)
- return debug_make_int_type (dhandle, 1, TRUE);
- else if (n3 == 0xffff)
- 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 || n2 == n3 + 1)
- {
- if (n3 == 0x7f)
- return debug_make_int_type (dhandle, 1, FALSE);
- else if (n3 == 0x7fff)
- return debug_make_int_type (dhandle, 2, FALSE);
- else if (n3 == 0x7fffffff)
- 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
- }
- }
-
- /* At this point I don't have the faintest idea how to deal with a
- self_subrange type; I'm going to assume that this is used as an
- idiom, and that all of them are special cases. So . . . */
- if (self_subrange)
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
-
- index_type = stab_find_type (dhandle, info, rangenums);
- if (index_type == DEBUG_TYPE_NULL)
- {
- /* 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);
- }
-
- return debug_make_range_type (dhandle, index_type, n2, n3);
-}
-
-/* Sun's ACC uses a somewhat saner method for specifying the builtin
- typedefs in every file (for int, long, etc):
-
- type = b <signed> <width>; <offset>; <nbits>
- signed = u or s. Possible c in addition to u or s (for char?).
- offset = offset from high order bit to start bit of type.
- width is # bytes in object of this type, nbits is # bits in type.
-
- The width/offset stuff appears to be for small objects stored in
- larger ones (e.g. `shorts' in `int' registers). We ignore it for now,
- FIXME. */
-
-static debug_type
-parse_stab_sun_builtin_type (void *dhandle, const char **pp)
-{
- const char *orig;
- bfd_boolean unsignedp;
- bfd_vma bits;
-
- orig = *pp;
-
- switch (**pp)
- {
- case 's':
- unsignedp = FALSE;
- break;
- case 'u':
- unsignedp = TRUE;
- break;
- default:
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- /* For some odd reason, all forms of char put a c here. This is strange
- because no other type has this honor. We can safely ignore this because
- we actually determine 'char'acterness by the number of bits specified in
- the descriptor. */
- if (**pp == 'c')
- ++*pp;
-
- /* The first number appears to be the number of bytes occupied
- 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, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- /* The second number is always 0, so ignore it too. */
- (void) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- /* 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
- the type ends. If this type is at the end of the stabstring we
- can deal with the omitted semicolon (but we don't have to like
- it). Don't bother to complain(), Sun's compiler omits the semicolon
- for "void". */
- if (**pp == ';')
- ++*pp;
-
- if (bits == 0)
- return debug_make_void_type (dhandle);
-
- return debug_make_int_type (dhandle, bits / 8, unsignedp);
-}
-
-/* Parse a builtin floating type generated by the Sun compiler. */
-
-static debug_type
-parse_stab_sun_floating_type (void *dhandle, const char **pp)
-{
- const char *orig;
- bfd_vma details;
- bfd_vma bytes;
-
- orig = *pp;
-
- /* The first number has more details about the type, for example
- FN_COMPLEX. */
- details = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
-
- /* The second number is the number of bytes occupied by this type */
- bytes = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
-
- if (details == NF_COMPLEX
- || details == NF_COMPLEX16
- || details == NF_COMPLEX32)
- return debug_make_complex_type (dhandle, bytes);
-
- return debug_make_float_type (dhandle, bytes);
-}
-
-/* Handle an enum type. */
-
-static debug_type
-parse_stab_enum_type (void *dhandle, const char **pp)
-{
- const char *orig;
- const char **names;
- bfd_signed_vma *values;
- unsigned int n;
- unsigned int alloc;
-
- orig = *pp;
-
- /* FIXME: gdb checks os9k_stabs here. */
-
- /* The aix4 compiler emits an extra field before the enum members;
- my guess is it's a type of some sort. Just ignore it. */
- if (**pp == '-')
- {
- while (**pp != ':')
- ++*pp;
- ++*pp;
- }
-
- /* Read the value-names and their values.
- The input syntax is NAME:VALUE,NAME:VALUE, and so on.
- A semicolon or comma instead of a NAME means the end. */
- alloc = 10;
- names = (const char **) xmalloc (alloc * sizeof *names);
- values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values);
- n = 0;
- while (**pp != '\0' && **pp != ';' && **pp != ',')
- {
- const char *p;
- char *name;
- bfd_signed_vma val;
-
- p = *pp;
- while (*p != ':')
- ++p;
-
- name = savestring (*pp, p - *pp);
-
- *pp = p + 1;
- val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- if (n + 1 >= alloc)
- {
- alloc += 10;
- names = ((const char **)
- xrealloc (names, alloc * sizeof *names));
- values = ((bfd_signed_vma *)
- xrealloc (values, alloc * sizeof *values));
- }
-
- names[n] = name;
- values[n] = val;
- ++n;
- }
-
- names[n] = NULL;
- values[n] = 0;
-
- if (**pp == ';')
- ++*pp;
-
- return debug_make_enum_type (dhandle, names, values);
-}
-
-/* Read the description of a structure (or union type) and return an object
- describing the type.
-
- PP points to a character pointer that points to the next unconsumed token
- 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 (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;
- bfd_boolean statics;
- debug_method *methods;
- debug_type vptrbase;
- bfd_boolean ownvptr;
-
- orig = *pp;
-
- /* Get the size. */
- size = parse_number (pp, (bfd_boolean *) NULL);
-
- /* Get the other information. */
- if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
- || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
- || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
- || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
- &ownvptr))
- return DEBUG_TYPE_NULL;
-
- if (! statics
- && baseclasses == NULL
- && methods == NULL
- && vptrbase == DEBUG_TYPE_NULL
- && ! ownvptr)
- return debug_make_struct_type (dhandle, structp, size, fields);
-
- return debug_make_object_type (dhandle, structp, size, fields, baseclasses,
- methods, vptrbase, ownvptr);
-}
-
-/* The stabs for C++ derived classes contain baseclass information which
- is marked by a '!' character after the total size. This function is
- called when we encounter the baseclass marker, and slurps up all the
- baseclass information.
-
- Immediately following the '!' marker is the number of base classes that
- the class is derived from, followed by information for each base class.
- For each base class, there are two visibility specifiers, a bit offset
- to the base class information within the derived class, a reference to
- 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 for base class ___________________________| | | |
- Visibility specifiers (2) _______________________________| | |
- Offset in bits from start of class ________________________| |
- Type number of base class ____________________________________|
-
- Return TRUE for success, FALSE for failure. */
-
-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;
- debug_baseclass *classes;
-
- *retp = NULL;
-
- orig = *pp;
-
- if (**pp != '!')
- {
- /* No base classes. */
- return TRUE;
- }
- ++*pp;
-
- c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL);
-
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp));
-
- for (i = 0; i < c; i++)
- {
- bfd_boolean virtual;
- enum debug_visibility visibility;
- bfd_vma bitpos;
- debug_type type;
-
- switch (**pp)
- {
- case '0':
- virtual = FALSE;
- break;
- case '1':
- virtual = TRUE;
- break;
- default:
- warn_stab (orig, _("unknown virtual character for baseclass"));
- virtual = FALSE;
- break;
- }
- ++*pp;
-
- switch (**pp)
- {
- case '0':
- visibility = DEBUG_VISIBILITY_PRIVATE;
- break;
- case '1':
- visibility = DEBUG_VISIBILITY_PROTECTED;
- break;
- case '2':
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- default:
- warn_stab (orig, _("unknown visibility character for baseclass"));
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- }
- ++*pp;
-
- /* 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, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (type == DEBUG_TYPE_NULL)
- return FALSE;
-
- classes[i] = debug_make_baseclass (dhandle, type, bitpos, virtual,
- visibility);
- if (classes[i] == DEBUG_BASECLASS_NULL)
- return FALSE;
-
- if (**pp != ';')
- return FALSE;
- ++*pp;
- }
-
- classes[i] = DEBUG_BASECLASS_NULL;
-
- *retp = classes;
-
- return TRUE;
-}
-
-/* Read struct or class data fields. They have the form:
-
- NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
-
- At the end, we see a semicolon instead of a field.
-
- In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
- a static field.
-
- The optional VISIBILITY is one of:
-
- '/0' (VISIBILITY_PRIVATE)
- '/1' (VISIBILITY_PROTECTED)
- '/2' (VISIBILITY_PUBLIC)
- '/9' (VISIBILITY_IGNORE)
-
- or nothing, for C style fields with public visibility.
-
- Returns 1 for success, 0 for failure. */
-
-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;
- debug_field *fields;
- unsigned int c;
- unsigned int alloc;
-
- *retp = NULL;
- *staticsp = FALSE;
-
- orig = *pp;
-
- c = 0;
- alloc = 10;
- fields = (debug_field *) xmalloc (alloc * sizeof *fields);
- while (**pp != ';')
- {
- /* FIXME: gdb checks os9k_stabs here. */
-
- p = *pp;
-
- /* Add 1 to c to leave room for NULL pointer at end. */
- if (c + 1 >= alloc)
- {
- alloc += 10;
- fields = ((debug_field *)
- xrealloc (fields, alloc * sizeof *fields));
- }
-
- /* If it starts with CPLUS_MARKER it is a special abbreviation,
- unless the CPLUS_MARKER is followed by an underscore, in
- which case it is just the name of an anonymous type, which we
- should handle like any other type name. We accept either '$'
- or '.', because a field name can never contain one of these
- characters except as a CPLUS_MARKER. */
-
- if ((*p == '$' || *p == '.') && p[1] != '_')
- {
- ++*pp;
- if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
- 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. */
-
- p = strchr (p, ':');
- if (p == NULL)
- {
- bad_stab (orig);
- return FALSE;
- }
-
- if (p[1] == ':')
- break;
-
- if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
- staticsp))
- return FALSE;
-
- ++c;
- }
-
- fields[c] = DEBUG_FIELD_NULL;
-
- *retp = fields;
-
- return TRUE;
-}
-
-/* Special GNU C++ name. */
-
-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;
- debug_type context;
- const char *name;
- const char *typename;
- debug_type type;
- bfd_vma bitpos;
-
- *retp = DEBUG_FIELD_NULL;
-
- orig = *pp;
-
- if (**pp != 'v')
- {
- bad_stab (*pp);
- return FALSE;
- }
- ++*pp;
-
- cpp_abbrev = **pp;
- ++*pp;
-
- /* At this point, *pp points to something like "22:23=*22...", where
- the type number before the ':' is the "context" and everything
- after is a regular type definition. Lookup the type, find it's
- name, and construct the field name. */
-
- context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (context == DEBUG_TYPE_NULL)
- return FALSE;
-
- switch (cpp_abbrev)
- {
- case 'f':
- /* $vf -- a virtual function table pointer. */
- name = "_vptr$";
- break;
- case 'b':
- /* $vb -- a virtual bsomethingorother */
- typename = debug_get_type_name (dhandle, context);
- if (typename == NULL)
- {
- warn_stab (orig, _("unnamed $vb type"));
- typename = "FOO";
- }
- name = concat ("_vb$", typename, (const char *) NULL);
- break;
- default:
- warn_stab (orig, _("unrecognized C++ abbreviation"));
- name = "INVALID_CPLUSPLUS_ABBREV";
- break;
- }
-
- if (**pp != ':')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- *retp = debug_make_field (dhandle, name, type, bitpos, 0,
- DEBUG_VISIBILITY_PRIVATE);
- if (*retp == DEBUG_FIELD_NULL)
- return FALSE;
-
- return TRUE;
-}
-
-/* Parse a single field in a struct or union. */
-
-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;
- enum debug_visibility visibility;
- debug_type type;
- bfd_vma bitpos;
- bfd_vma bitsize;
-
- orig = *pp;
-
- /* FIXME: gdb checks ARM_DEMANGLING here. */
-
- name = savestring (*pp, p - *pp);
-
- *pp = p + 1;
-
- if (**pp != '/')
- visibility = DEBUG_VISIBILITY_PUBLIC;
- else
- {
- ++*pp;
- switch (**pp)
- {
- case '0':
- visibility = DEBUG_VISIBILITY_PRIVATE;
- break;
- case '1':
- visibility = DEBUG_VISIBILITY_PROTECTED;
- break;
- case '2':
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- default:
- warn_stab (orig, _("unknown visibility character for field"));
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- }
- ++*pp;
- }
-
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (type == DEBUG_TYPE_NULL)
- return FALSE;
-
- if (**pp == ':')
- {
- char *varname;
-
- /* This is a static class member. */
- ++*pp;
- p = strchr (*pp, ';');
- if (p == NULL)
- {
- bad_stab (orig);
- return FALSE;
- }
-
- varname = savestring (*pp, p - *pp);
-
- *pp = p + 1;
-
- *retp = debug_make_static_member (dhandle, name, type, varname,
- visibility);
- *staticsp = TRUE;
-
- return TRUE;
- }
-
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- bitsize = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
-
- if (bitpos == 0 && bitsize == 0)
- {
- /* This can happen in two cases: (1) at least for gcc 2.4.5 or
- so, it is a field which has been optimized out. The correct
- stab for this case is to use VISIBILITY_IGNORE, but that is a
- recent invention. (2) It is a 0-size array. For example
- union { int num; char str[0]; } foo. Printing "<no value>"
- for str in "p foo" is OK, since foo.str (and thus foo.str[3])
- will continue to work, and a 0-size array as a whole doesn't
- have any contents to print.
-
- I suspect this probably could also happen with gcc -gstabs
- (not -gstabs+) for static fields, and perhaps other C++
- extensions. Hopefully few people use -gstabs with gdb, since
- it is intended for dbx compatibility. */
- visibility = DEBUG_VISIBILITY_IGNORE;
- }
-
- /* FIXME: gdb does some stuff here to mark fields as unpacked. */
-
- *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility);
-
- return TRUE;
-}
-
-/* Read member function stabs info for C++ classes. The form of each member
- function data is:
-
- NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ;
-
- An example with two member functions is:
-
- afunc1::20=##15;:i;2A.;afunc2::20:i;2A.;
-
- For the case of overloaded operators, the format is op$::*.funcs, where
- $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
- name (such as `+=') and `.' marks the end of the operator name. */
-
-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;
- unsigned int c;
- unsigned int alloc;
-
- *retp = NULL;
-
- orig = *pp;
-
- alloc = 0;
- methods = NULL;
- c = 0;
-
- while (**pp != ';')
- {
- const char *p;
- char *name;
- debug_method_variant *variants;
- unsigned int cvars;
- unsigned int allocvars;
- debug_type look_ahead_type;
-
- p = strchr (*pp, ':');
- if (p == NULL || p[1] != ':')
- break;
-
- /* FIXME: Some systems use something other than '$' here. */
- if ((*pp)[0] != 'o' || (*pp)[1] != 'p' || (*pp)[2] != '$')
- {
- name = savestring (*pp, p - *pp);
- *pp = p + 2;
- }
- else
- {
- /* 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
- format is "op$::XXXX." where XXXX is the name. This is
- used for names like "+" or "=". YUUUUUUUK! FIXME! */
- *pp = p + 2;
- for (p = *pp; *p != '.' && *p != '\0'; p++)
- ;
- if (*p != '.')
- {
- bad_stab (orig);
- return FALSE;
- }
- name = savestring (*pp, p - *pp);
- *pp = p + 1;
- }
-
- allocvars = 10;
- variants = ((debug_method_variant *)
- xmalloc (allocvars * sizeof *variants));
- cvars = 0;
-
- look_ahead_type = DEBUG_TYPE_NULL;
-
- do
- {
- debug_type type;
- bfd_boolean stub;
- char *argtypes;
- enum debug_visibility visibility;
- bfd_boolean constp, volatilep, staticp;
- bfd_vma voffset;
- debug_type context;
- const char *physname;
- bfd_boolean varargs;
-
- if (look_ahead_type != DEBUG_TYPE_NULL)
- {
- /* g++ version 1 kludge */
- type = look_ahead_type;
- look_ahead_type = DEBUG_TYPE_NULL;
- }
- else
- {
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (type == DEBUG_TYPE_NULL)
- return FALSE;
- if (**pp != ':')
- {
- bad_stab (orig);
- return FALSE;
- }
- }
-
- ++*pp;
- p = strchr (*pp, ';');
- if (p == NULL)
- {
- bad_stab (orig);
- 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;
-
- switch (**pp)
- {
- case '0':
- visibility = DEBUG_VISIBILITY_PRIVATE;
- break;
- case '1':
- visibility = DEBUG_VISIBILITY_PROTECTED;
- break;
- default:
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- }
- ++*pp;
-
- constp = FALSE;
- volatilep = FALSE;
- switch (**pp)
- {
- case 'A':
- /* Normal function. */
- ++*pp;
- break;
- case 'B':
- /* const member function. */
- constp = TRUE;
- ++*pp;
- break;
- case 'C':
- /* volatile member function. */
- volatilep = TRUE;
- ++*pp;
- break;
- case 'D':
- /* const volatile member function. */
- constp = TRUE;
- volatilep = TRUE;
- ++*pp;
- break;
- case '*':
- case '?':
- case '.':
- /* File compiled with g++ version 1; no information. */
- break;
- default:
- warn_stab (orig, _("const/volatile indicator missing"));
- break;
- }
-
- staticp = FALSE;
- switch (**pp)
- {
- case '*':
- /* virtual member function, followed by index. The sign
- bit is supposedly set to distinguish
- pointers-to-methods from virtual function indicies. */
- ++*pp;
- voffset = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- voffset &= 0x7fffffff;
-
- if (**pp == ';' || *pp == '\0')
- {
- /* Must be g++ version 1. */
- context = DEBUG_TYPE_NULL;
- }
- else
- {
- /* 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. */
- 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;
- voffset = 0;
- context = DEBUG_TYPE_NULL;
- if (strncmp (argtypes, name, strlen (name)) != 0)
- stub = TRUE;
- break;
-
- default:
- warn_stab (orig, "member function type missing");
- voffset = 0;
- context = DEBUG_TYPE_NULL;
- break;
-
- case '.':
- ++*pp;
- voffset = 0;
- context = DEBUG_TYPE_NULL;
- break;
- }
-
- /* 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
- {
- debug_type class_type, return_type;
-
- class_type = stab_find_type (dhandle, info, typenums);
- if (class_type == DEBUG_TYPE_NULL)
- return FALSE;
- return_type = debug_get_return_type (dhandle, type);
- if (return_type == DEBUG_TYPE_NULL)
- {
- bad_stab (orig);
- 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;
- }
-
- if (cvars + 1 >= allocvars)
- {
- allocvars += 10;
- variants = ((debug_method_variant *)
- xrealloc (variants,
- allocvars * sizeof *variants));
- }
-
- if (! staticp)
- variants[cvars] = debug_make_method_variant (dhandle, physname,
- type, visibility,
- constp, volatilep,
- voffset, context);
- else
- variants[cvars] = debug_make_static_method_variant (dhandle,
- physname,
- type,
- visibility,
- constp,
- volatilep);
- if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
- return FALSE;
-
- ++cvars;
- }
- while (**pp != ';' && **pp != '\0');
-
- variants[cvars] = DEBUG_METHOD_VARIANT_NULL;
-
- if (**pp != '\0')
- ++*pp;
-
- if (c + 1 >= alloc)
- {
- alloc += 10;
- methods = ((debug_method *)
- xrealloc (methods, alloc * sizeof *methods));
- }
-
- methods[c] = debug_make_method (dhandle, name, variants);
-
- ++c;
- }
-
- if (methods != NULL)
- methods[c] = DEBUG_METHOD_NULL;
-
- *retp = methods;
-
- return TRUE;
-}
-
-/* Parse a string representing argument types for a method. Stabs
- tries to save space by packing argument types into a mangled
- string. This string should give us enough information to extract
- both argument types and the physical name of the function, given
- the tag name. */
-
-static debug_type
-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)
-{
- bfd_boolean is_full_physname_constructor;
- bfd_boolean is_constructor;
- bfd_boolean is_destructor;
- bfd_boolean is_v3;
- debug_type *args;
- bfd_boolean varargs;
- unsigned int physname_len = 0;
-
- /* Constructors are sometimes handled specially. */
- is_full_physname_constructor = ((argtypes[0] == '_'
- && argtypes[1] == '_'
- && (ISDIGIT (argtypes[2])
- || argtypes[2] == 'Q'
- || argtypes[2] == 't'))
- || strncmp (argtypes, "__ct", 4) == 0);
-
- is_constructor = (is_full_physname_constructor
- || (tagname != NULL
- && strcmp (fieldname, tagname) == 0));
- is_destructor = ((argtypes[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 || is_v3)
- *pphysname = argtypes;
- else
- {
- unsigned int len;
- const char *const_prefix;
- const char *volatile_prefix;
- char buf[20];
- unsigned int mangled_name_len;
- char *physname;
-
- len = tagname == NULL ? 0 : strlen (tagname);
- const_prefix = constp ? "C" : "";
- volatile_prefix = volatilep ? "V" : "";
-
- if (len == 0)
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
- else if (tagname != NULL && strchr (tagname, '<') != NULL)
- {
- /* Template methods are fully mangled. */
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
- tagname = NULL;
- len = 0;
- }
- else
- sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
-
- mangled_name_len = ((is_constructor ? 0 : strlen (fieldname))
- + strlen (buf)
- + len
- + strlen (argtypes)
- + 1);
-
- if (fieldname[0] == 'o'
- && fieldname[1] == 'p'
- && (fieldname[2] == '$' || fieldname[2] == '.'))
- {
- const char *opname;
-
- opname = cplus_mangle_opname (fieldname + 3, 0);
- if (opname == NULL)
- {
- fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname);
- return DEBUG_TYPE_NULL;
- }
- mangled_name_len += strlen (opname);
- physname = (char *) xmalloc (mangled_name_len);
- strncpy (physname, fieldname, 3);
- strcpy (physname + 3, opname);
- }
- else
- {
- physname = (char *) xmalloc (mangled_name_len);
- if (is_constructor)
- physname[0] = '\0';
- else
- strcpy (physname, fieldname);
- }
-
- physname_len = strlen (physname);
- strcat (physname, buf);
- if (tagname != NULL)
- strcat (physname, tagname);
- strcat (physname, argtypes);
-
- *pphysname = physname;
- }
-
- 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);
- }
-
- args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs, physname_len);
- if (args == NULL)
- return DEBUG_TYPE_NULL;
-
- return debug_make_method_type (dhandle, return_type, class_type, args,
- varargs);
-}
-
-/* The tail end of stabs for C++ classes that contain a virtual function
- pointer contains a tilde, a %, and a type number.
- The type number refers to the base class (possibly this class itself) which
- contains the vtable pointer for the current class.
-
- This function is called when we have parsed all the method declarations,
- so we can look for the vptr base class info. */
-
-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;
-
- orig = *pp;
-
- /* If we are positioned at a ';', then skip it. */
- if (**pp == ';')
- ++*pp;
-
- if (**pp != '~')
- return TRUE;
-
- ++*pp;
-
- if (**pp == '=' || **pp == '+' || **pp == '-')
- {
- /* Obsolete flags that used to indicate the presence of
- constructors and/or destructors. */
- ++*pp;
- }
-
- if (**pp != '%')
- return TRUE;
-
- ++*pp;
-
- hold = *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;
-
- if (vtypenums[0] == typenums[0]
- && vtypenums[1] == typenums[1])
- *retownvptr = TRUE;
- else
- {
- debug_type vtype;
- const char *p;
-
- *pp = hold;
-
- vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- for (p = *pp; *p != ';' && *p != '\0'; p++)
- ;
- if (*p != ';')
- {
- bad_stab (orig);
- return FALSE;
- }
-
- *retvptrbase = vtype;
-
- *pp = p + 1;
- }
-
- return TRUE;
-}
-
-/* Read a definition of an array type. */
-
-static debug_type
-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;
- bfd_boolean adjustable;
- bfd_signed_vma lower, upper;
- debug_type element_type;
-
- /* Format of an array type:
- "ar<index type>;lower;upper;<array_contents_type>".
- OS9000: "arlower,upper;<array_contents_type>".
-
- Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
- for these, produce a type like float[][]. */
-
- orig = *pp;
-
- /* FIXME: gdb checks os9k_stabs here. */
-
- /* 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);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- adjustable = FALSE;
-
- if (! ISDIGIT (**pp) && **pp != '-')
- {
- ++*pp;
- adjustable = TRUE;
- }
-
- lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- if (! ISDIGIT (**pp) && **pp != '-')
- {
- ++*pp;
- adjustable = TRUE;
- }
-
- upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- 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 DEBUG_TYPE_NULL;
-
- if (adjustable)
- {
- lower = 0;
- upper = -1;
- }
-
- return debug_make_array_type (dhandle, element_type, index_type, lower,
- upper, stringp);
-}
-
-/* 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 (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_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 (info->file_types,
- (info->files
- * sizeof *info->file_types)));
- 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 (struct stab_handle *info)
-{
- struct bincl_file *o;
-
- o = info->bincl_stack;
- if (o == NULL)
- return info->main_filename;
- 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 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;
-
- if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
- || ! info->within_function
- || (info->gcc_compiled == 0 && info->n_opt_found))
- return debug_record_variable (dhandle, name, type, kind, val);
-
- v = (struct stab_pending_var *) xmalloc (sizeof *v);
- memset (v, 0, sizeof *v);
-
- v->next = info->pending;
- v->name = name;
- v->type = type;
- v->kind = kind;
- v->val = val;
- info->pending = v;
-
- return TRUE;
-}
-
-/* Emit pending variable definitions. This is called after we see the
- N_LBRAC that starts the block. */
-
-static bfd_boolean
-stab_emit_pending_vars (void *dhandle, struct stab_handle *info)
-{
- struct stab_pending_var *v;
-
- v = info->pending;
- while (v != NULL)
- {
- struct stab_pending_var *next;
-
- if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val))
- return FALSE;
-
- next = v->next;
- free (v);
- v = next;
- }
-
- info->pending = NULL;
-
- return TRUE;
-}
-
-/* Find the slot for a type in the database. */
-
-static debug_type *
-stab_find_slot (struct stab_handle *info, const int *typenums)
-{
- int filenum;
- int index;
- struct stab_types **ps;
-
- filenum = typenums[0];
- index = typenums[1];
-
- if (filenum < 0 || (unsigned int) filenum >= info->files)
- {
- fprintf (stderr, _("Type file number %d out of range\n"), filenum);
- return NULL;
- }
- if (index < 0)
- {
- fprintf (stderr, _("Type index number %d out of range\n"), index);
- return NULL;
- }
-
- ps = info->file_types + filenum;
-
- while (index >= STAB_TYPES_SLOTS)
- {
- if (*ps == NULL)
- {
- *ps = (struct stab_types *) xmalloc (sizeof **ps);
- memset (*ps, 0, sizeof **ps);
- }
- ps = &(*ps)->next;
- index -= STAB_TYPES_SLOTS;
- }
- if (*ps == NULL)
- {
- *ps = (struct stab_types *) xmalloc (sizeof **ps);
- memset (*ps, 0, sizeof **ps);
- }
-
- return (*ps)->types + index;
-}
-
-/* Find a type given a type number. If the type has not been
- allocated yet, create an indirect type. */
-
-static debug_type
-stab_find_type (void *dhandle, struct stab_handle *info, const int *typenums)
-{
- debug_type *slot;
-
- if (typenums[0] == 0 && typenums[1] < 0)
- {
- /* A negative type number indicates an XCOFF builtin type. */
- return stab_xcoff_builtin_type (dhandle, info, typenums[1]);
- }
-
- slot = stab_find_slot (info, typenums);
- if (slot == NULL)
- return DEBUG_TYPE_NULL;
-
- if (*slot == DEBUG_TYPE_NULL)
- return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
-
- return *slot;
-}
-
-/* Record that a given type number refers to a given 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;
-
- /* gdb appears to ignore type redefinitions, so we do as well. */
-
- *slot = type;
-
- return TRUE;
-}
-
-/* Return an XCOFF builtin type. */
-
-static debug_type
-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);
- return DEBUG_TYPE_NULL;
- }
- if (info->xcoff_types[-typenum] != NULL)
- return info->xcoff_types[-typenum];
-
- switch (-typenum)
- {
- case 1:
- /* 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);
- break;
- case 2:
- name = "char";
- rettype = debug_make_int_type (dhandle, 1, FALSE);
- break;
- case 3:
- name = "short";
- rettype = debug_make_int_type (dhandle, 2, FALSE);
- break;
- case 4:
- name = "long";
- rettype = debug_make_int_type (dhandle, 4, FALSE);
- break;
- case 5:
- name = "unsigned char";
- rettype = debug_make_int_type (dhandle, 1, TRUE);
- break;
- case 6:
- name = "signed char";
- rettype = debug_make_int_type (dhandle, 1, FALSE);
- break;
- case 7:
- name = "unsigned short";
- rettype = debug_make_int_type (dhandle, 2, TRUE);
- break;
- case 8:
- name = "unsigned int";
- rettype = debug_make_int_type (dhandle, 4, TRUE);
- break;
- case 9:
- name = "unsigned";
- rettype = debug_make_int_type (dhandle, 4, TRUE);
- case 10:
- name = "unsigned long";
- rettype = debug_make_int_type (dhandle, 4, TRUE);
- break;
- case 11:
- name = "void";
- rettype = debug_make_void_type (dhandle);
- break;
- case 12:
- /* IEEE single precision (32 bit). */
- name = "float";
- rettype = debug_make_float_type (dhandle, 4);
- break;
- case 13:
- /* IEEE double precision (64 bit). */
- name = "double";
- rettype = debug_make_float_type (dhandle, 8);
- break;
- case 14:
- /* This is an IEEE double on the RS/6000, and different machines
- with different sizes for "long double" should use different
- negative type numbers. See stabs.texinfo. */
- name = "long double";
- rettype = debug_make_float_type (dhandle, 8);
- break;
- case 15:
- name = "integer";
- rettype = debug_make_int_type (dhandle, 4, FALSE);
- break;
- case 16:
- name = "boolean";
- rettype = debug_make_bool_type (dhandle, 4);
- break;
- case 17:
- name = "short real";
- rettype = debug_make_float_type (dhandle, 4);
- break;
- case 18:
- name = "real";
- rettype = debug_make_float_type (dhandle, 8);
- break;
- case 19:
- /* FIXME */
- name = "stringptr";
- rettype = NULL;
- break;
- case 20:
- /* FIXME */
- name = "character";
- rettype = debug_make_int_type (dhandle, 1, TRUE);
- break;
- case 21:
- name = "logical*1";
- rettype = debug_make_bool_type (dhandle, 1);
- break;
- case 22:
- name = "logical*2";
- rettype = debug_make_bool_type (dhandle, 2);
- break;
- case 23:
- name = "logical*4";
- rettype = debug_make_bool_type (dhandle, 4);
- break;
- case 24:
- name = "logical";
- rettype = debug_make_bool_type (dhandle, 4);
- break;
- case 25:
- /* Complex type consisting of two IEEE single precision values. */
- name = "complex";
- rettype = debug_make_complex_type (dhandle, 8);
- break;
- case 26:
- /* Complex type consisting of two IEEE double precision values. */
- name = "double complex";
- rettype = debug_make_complex_type (dhandle, 16);
- break;
- case 27:
- name = "integer*1";
- rettype = debug_make_int_type (dhandle, 1, FALSE);
- break;
- case 28:
- name = "integer*2";
- rettype = debug_make_int_type (dhandle, 2, FALSE);
- break;
- case 29:
- name = "integer*4";
- rettype = debug_make_int_type (dhandle, 4, FALSE);
- break;
- case 30:
- /* FIXME */
- name = "wchar";
- rettype = debug_make_int_type (dhandle, 2, FALSE);
- break;
- case 31:
- name = "long long";
- rettype = debug_make_int_type (dhandle, 8, FALSE);
- break;
- case 32:
- name = "unsigned long long";
- rettype = debug_make_int_type (dhandle, 8, TRUE);
- break;
- case 33:
- name = "logical*8";
- rettype = debug_make_bool_type (dhandle, 8);
- break;
- case 34:
- name = "integer*8";
- rettype = debug_make_int_type (dhandle, 8, FALSE);
- break;
- default:
- abort ();
- }
-
- rettype = debug_name_type (dhandle, name, rettype);
-
- info->xcoff_types[-typenum] = rettype;
-
- return rettype;
-}
-
-/* Find or create a tagged type. */
-
-static debug_type
-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_tag *st;
-
- name = savestring (p, len);
-
- /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same
- namespace. This is right for C, and I don't know how to handle
- other languages. FIXME. */
- dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL);
- if (dtype != DEBUG_TYPE_NULL)
- {
- free (name);
- return dtype;
- }
-
- /* We need to allocate an entry on the undefined tag list. */
- for (st = info->tags; st != NULL; st = st->next)
- {
- if (st->name[0] == name[0]
- && strcmp (st->name, name) == 0)
- {
- if (st->kind == DEBUG_KIND_ILLEGAL)
- st->kind = kind;
- free (name);
- break;
- }
- }
- if (st == NULL)
- {
- st = (struct stab_tag *) xmalloc (sizeof *st);
- memset (st, 0, sizeof *st);
-
- st->next = info->tags;
- st->name = name;
- st->kind = kind;
- st->slot = DEBUG_TYPE_NULL;
- st->type = debug_make_indirect_type (dhandle, &st->slot, name);
- info->tags = st;
- }
-
- return st->type;
-}
-
-/* In order to get the correct argument types for a stubbed method, we
- need to extract the argument types from a C++ mangled string.
- Since the argument types can refer back to the return type, this
- means that we must demangle the entire physical name. In gdb this
- is done by calling cplus_demangle and running the results back
- through the C++ expression parser. Since we have no expression
- parser, we must duplicate much of the work of cplus_demangle here.
-
- We assume that GNU style demangling is used, since this is only
- done for method stubs, and only g++ should output that form of
- debugging information. */
-
-/* This structure is used to hold a pointer to type information which
- demangling a string. */
-
-struct stab_demangle_typestring
-{
- /* The start of the type. This is not null terminated. */
- const char *typestring;
- /* The length of the type. */
- unsigned int len;
-};
-
-/* This structure is used to hold information while demangling a
- string. */
-
-struct stab_demangle_info
-{
- /* The debugging information handle. */
- 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. */
- bfd_boolean varargs;
- /* The array of types we have remembered. */
- struct stab_demangle_typestring *typestrings;
- /* The number of typestrings. */
- unsigned int typestring_count;
- /* The number of typestring slots we have allocated. */
- unsigned int typestring_alloc;
-};
-
-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 (const char *s)
-{
- fprintf (stderr, _("bad mangled name `%s'\n"), s);
-}
-
-/* Get a count from a stab string. */
-
-static unsigned int
-stab_demangle_count (const char **pp)
-{
- unsigned int count;
-
- count = 0;
- while (ISDIGIT (**pp))
- {
- count *= 10;
- count += **pp - '0';
- ++*pp;
- }
- return count;
-}
-
-/* Require a count in a string. The count may be multiple digits, in
- which case it must end in an underscore. */
-
-static bfd_boolean
-stab_demangle_get_count (const char **pp, unsigned int *pi)
-{
- if (! ISDIGIT (**pp))
- return FALSE;
-
- *pi = **pp - '0';
- ++*pp;
- if (ISDIGIT (**pp))
- {
- unsigned int count;
- const char *p;
-
- count = *pi;
- p = *pp;
- do
- {
- count *= 10;
- count += *p - '0';
- ++p;
- }
- while (ISDIGIT (*p));
- if (*p == '_')
- {
- *pp = p + 1;
- *pi = count;
- }
- }
-
- return TRUE;
-}
-
-/* This function demangles a physical name, returning a NULL
- terminated array of argument types. */
-
-static debug_type *
-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.typestring_alloc = 10;
- minfo.typestrings = ((struct stab_demangle_typestring *)
- xmalloc (minfo.typestring_alloc
- * sizeof *minfo.typestrings));
- minfo.typestring_count = 0;
-
- /* 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, physname_len))
- goto error_return;
-
- if (*physname != '\0')
- {
- if (! stab_demangle_signature (&minfo, &physname))
- goto error_return;
- }
-
- free (minfo.typestrings);
- minfo.typestrings = NULL;
-
- if (minfo.args == NULL)
- fprintf (stderr, _("no argument types in mangled string\n"));
-
- *pvarargs = minfo.varargs;
- return minfo.args;
-
- error_return:
- if (minfo.typestrings != NULL)
- free (minfo.typestrings);
- return NULL;
-}
-
-/* Demangle the prefix of the mangled name. */
-
-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. */
-
- if (physname_len)
- scan = *pp + physname_len;
- else
- {
- /* Look for `__'. */
- scan = *pp;
- do
- scan = strchr (scan, '_');
- while (scan != NULL && *++scan != '_');
-
- if (scan == NULL)
- {
- stab_bad_demangle (*pp);
- return FALSE;
- }
-
- --scan;
-
- /* We found `__'; move ahead to the last contiguous `__' pair. */
- i = strspn (scan, "_");
- if (i > 2)
- scan += i - 2;
- }
-
- if (scan == *pp
- && (ISDIGIT (scan[2])
- || scan[2] == 'Q'
- || scan[2] == 't'))
- {
- /* This is a GNU style constructor name. */
- *pp = scan + 2;
- return TRUE;
- }
- else if (scan == *pp
- && ! ISDIGIT (scan[2])
- && scan[2] != 't')
- {
- /* Look for the `__' that separates the prefix from the
- signature. */
- while (*scan == '_')
- ++scan;
- scan = strstr (scan, "__");
- if (scan == NULL || scan[2] == '\0')
- {
- stab_bad_demangle (*pp);
- return FALSE;
- }
-
- return stab_demangle_function_name (minfo, pp, scan);
- }
- else if (scan[2] != '\0')
- {
- /* The name doesn't start with `__', but it does contain `__'. */
- return stab_demangle_function_name (minfo, pp, scan);
- }
- else
- {
- stab_bad_demangle (*pp);
- return FALSE;
- }
- /*NOTREACHED*/
-}
-
-/* Demangle a function name prefix. The scan argument points to the
- double underscore which separates the function name from the
- signature. */
-
-static bfd_boolean
-stab_demangle_function_name (struct stab_demangle_info *minfo,
- const char **pp, const char *scan)
-{
- const char *name;
-
- /* The string from *pp to scan is the name of the function. We
- don't care about the name, since we just looking for argument
- types. However, for conversion operators, the name may include a
- type which we must remember in order to handle backreferences. */
-
- name = *pp;
- *pp = scan + 2;
-
- if (*pp - name >= 5
- && strncmp (name, "type", 4) == 0
- && (name[4] == '$' || name[4] == '.'))
- {
- const char *tem;
-
- /* This is a type conversion operator. */
- tem = name + 5;
- if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
- return FALSE;
- }
- else if (name[0] == '_'
- && name[1] == '_'
- && name[2] == 'o'
- && name[3] == 'p')
- {
- const char *tem;
-
- /* This is a type conversion operator. */
- tem = name + 4;
- if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Demangle the signature. This is where the argument types are
- found. */
-
-static bfd_boolean
-stab_demangle_signature (struct stab_demangle_info *minfo, const char **pp)
-{
- const char *orig;
- bfd_boolean expect_func, func_done;
- const char *hold;
-
- orig = *pp;
-
- expect_func = FALSE;
- func_done = FALSE;
- hold = NULL;
-
- while (**pp != '\0')
- {
- switch (**pp)
- {
- case 'Q':
- hold = *pp;
- if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL)
- || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return FALSE;
- expect_func = TRUE;
- hold = NULL;
- break;
-
- case 'S':
- /* Static member function. FIXME: Can this happen? */
- if (hold == NULL)
- hold = *pp;
- ++*pp;
- break;
-
- case 'C':
- /* Const member function. */
- if (hold == NULL)
- hold = *pp;
- ++*pp;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (hold == NULL)
- hold = *pp;
- if (! stab_demangle_class (minfo, pp, (const char **) NULL)
- || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return FALSE;
- expect_func = TRUE;
- hold = NULL;
- break;
-
- case 'F':
- /* Function. I don't know if this actually happens with g++
- output. */
- hold = NULL;
- func_done = TRUE;
- ++*pp;
- if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return FALSE;
- break;
-
- case 't':
- /* Template. */
- if (hold == NULL)
- hold = *pp;
- if (! stab_demangle_template (minfo, pp, (char **) NULL)
- || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return FALSE;
- hold = NULL;
- expect_func = TRUE;
- break;
-
- case '_':
- /* At the outermost level, we cannot have a return type
- specified, so if we run into another '_' at this point we
- are dealing with a mangled name that is either bogus, or
- 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;
-
- default:
- /* Assume we have stumbled onto the first outermost function
- argument token, and start processing args. */
- func_done = TRUE;
- if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return FALSE;
- break;
- }
-
- if (expect_func)
- {
- func_done = TRUE;
- if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return FALSE;
- }
- }
-
- if (! func_done)
- {
- /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
- bar__3fooi is 'foo::bar(int)'. We get here when we find the
- 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 TRUE;
-}
-
-/* Demangle a qualified name, such as "Q25Outer5Inner" which is the
- mangled form of "Outer::Inner". */
-
-static bfd_boolean
-stab_demangle_qualified (struct stab_demangle_info *minfo, const char **pp,
- debug_type *ptype)
-{
- const char *orig;
- const char *p;
- unsigned int qualifiers;
- debug_type context;
-
- orig = *pp;
-
- switch ((*pp)[1])
- {
- case '_':
- /* GNU mangled name with more than 9 classes. The count is
- preceded by an underscore (to distinguish it from the <= 9
- case) and followed by an underscore. */
- p = *pp + 2;
- if (! ISDIGIT (*p) || *p == '0')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- qualifiers = atoi (p);
- while (ISDIGIT (*p))
- ++p;
- if (*p != '_')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- *pp = p + 1;
- break;
-
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- qualifiers = (*pp)[1] - '0';
- /* Skip an optional underscore after the count. */
- if ((*pp)[2] == '_')
- ++*pp;
- *pp += 2;
- break;
-
- case '0':
- default:
- stab_bad_demangle (orig);
- return FALSE;
- }
-
- context = DEBUG_TYPE_NULL;
-
- /* Pick off the names. */
- while (qualifiers-- > 0)
- {
- if (**pp == '_')
- ++*pp;
- if (**pp == 't')
- {
- 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
- {
- unsigned int len;
-
- len = stab_demangle_count (pp);
- if (strlen (*pp) < len)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
-
- if (ptype != NULL)
- {
- const debug_field *fields;
-
- fields = NULL;
- if (context != DEBUG_TYPE_NULL)
- fields = debug_get_fields (minfo->dhandle, context);
-
- context = DEBUG_TYPE_NULL;
-
- if (fields != NULL)
- {
- char *name;
-
- /* Try to find the type by looking through the
- fields of context until we find a field with the
- same type. This ought to work for a class
- defined within a class, but it won't work for,
- e.g., an enum defined within a class. stabs does
- not give us enough information to figure out the
- latter case. */
-
- name = savestring (*pp, len);
-
- for (; *fields != DEBUG_FIELD_NULL; fields++)
- {
- debug_type ft;
- const char *dn;
-
- ft = debug_get_field_type (minfo->dhandle, *fields);
- if (ft == NULL)
- return FALSE;
- dn = debug_get_type_name (minfo->dhandle, ft);
- if (dn != NULL && strcmp (dn, name) == 0)
- {
- context = ft;
- break;
- }
- }
-
- free (name);
- }
-
- if (context == DEBUG_TYPE_NULL)
- {
- /* 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. */
-
- if (qualifiers == 0)
- {
- char *name;
-
- name = savestring (*pp, len);
- context = debug_find_named_type (minfo->dhandle,
- name);
- free (name);
- }
-
- if (context == DEBUG_TYPE_NULL)
- {
- context = stab_find_tagged_type (minfo->dhandle,
- minfo->info,
- *pp, len,
- (qualifiers == 0
- ? DEBUG_KIND_ILLEGAL
- : DEBUG_KIND_CLASS));
- if (context == DEBUG_TYPE_NULL)
- return FALSE;
- }
- }
- }
-
- *pp += len;
- }
- }
-
- if (ptype != NULL)
- *ptype = context;
-
- return TRUE;
-}
-
-/* Demangle a template. If PNAME is not NULL, this sets *PNAME to a
- string representation of the template. */
-
-static bfd_boolean
-stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
- char **pname)
-{
- const char *orig;
- unsigned int r, i;
-
- orig = *pp;
-
- ++*pp;
-
- /* Skip the template name. */
- r = stab_demangle_count (pp);
- if (r == 0 || strlen (*pp) < r)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- *pp += r;
-
- /* Get the size of the parameter list. */
- if (stab_demangle_get_count (pp, &r) == 0)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
-
- for (i = 0; i < r; i++)
- {
- if (**pp == 'Z')
- {
- /* This is a type parameter. */
- ++*pp;
- if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
- return FALSE;
- }
- else
- {
- const char *old_p;
- 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;
-
- /* This is a value parameter. */
-
- if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
- return FALSE;
-
- while (*old_p != '\0' && ! done)
- {
- switch (*old_p)
- {
- case 'P':
- case 'p':
- case 'R':
- pointerp = TRUE;
- done = TRUE;
- break;
- case 'C': /* Const. */
- case 'S': /* Signed. */
- case 'U': /* Unsigned. */
- case 'V': /* Volatile. */
- case 'F': /* Function. */
- case 'M': /* Member function. */
- case 'O': /* ??? */
- ++old_p;
- break;
- case 'Q': /* Qualified name. */
- integralp = TRUE;
- done = TRUE;
- break;
- case 'T': /* Remembered type. */
- abort ();
- case 'v': /* Void. */
- abort ();
- case 'x': /* Long long. */
- case 'l': /* Long. */
- case 'i': /* Int. */
- case 's': /* Short. */
- case 'w': /* Wchar_t. */
- integralp = TRUE;
- done = TRUE;
- break;
- case 'b': /* Bool. */
- boolp = TRUE;
- done = TRUE;
- break;
- case 'c': /* Char. */
- charp = TRUE;
- done = TRUE;
- break;
- case 'r': /* Long double. */
- case 'd': /* Double. */
- case 'f': /* Float. */
- realp = TRUE;
- done = TRUE;
- break;
- default:
- /* Assume it's a user defined integral type. */
- integralp = TRUE;
- done = TRUE;
- break;
- }
- }
-
- if (integralp)
- {
- if (**pp == 'm')
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- }
- else if (charp)
- {
- unsigned int val;
-
- if (**pp == 'm')
- ++*pp;
- val = stab_demangle_count (pp);
- if (val == 0)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- }
- else if (boolp)
- {
- unsigned int val;
-
- val = stab_demangle_count (pp);
- if (val != 0 && val != 1)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- }
- else if (realp)
- {
- if (**pp == 'm')
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- if (**pp == '.')
- {
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- }
- if (**pp == 'e')
- {
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- }
- }
- else if (pointerp)
- {
- unsigned int len;
-
- len = stab_demangle_count (pp);
- if (len == 0)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- *pp += len;
- }
- }
- }
-
- /* 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 bfd_boolean
-stab_demangle_class (struct stab_demangle_info *minfo ATTRIBUTE_UNUSED,
- const char **pp, const char **pstart)
-{
- const char *orig;
- unsigned int n;
-
- orig = *pp;
-
- n = stab_demangle_count (pp);
- if (strlen (*pp) < n)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
-
- if (pstart != NULL)
- *pstart = *pp;
-
- *pp += n;
-
- return TRUE;
-}
-
-/* Demangle function arguments. If the pargs argument is not NULL, it
- is set to a NULL terminated array holding the arguments. */
-
-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;
-
- orig = *pp;
-
- alloc = 10;
- if (pargs != NULL)
- {
- *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
- *pvarargs = FALSE;
- }
- count = 0;
-
- while (**pp != '_' && **pp != '\0' && **pp != 'e')
- {
- if (**pp == 'N' || **pp == 'T')
- {
- char temptype;
- unsigned int r, t;
-
- temptype = **pp;
- ++*pp;
-
- if (temptype == 'T')
- r = 1;
- else
- {
- if (! stab_demangle_get_count (pp, &r))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- }
-
- if (! stab_demangle_get_count (pp, &t))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
-
- if (t >= minfo->typestring_count)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- while (r-- > 0)
- {
- const char *tem;
-
- tem = minfo->typestrings[t].typestring;
- if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc))
- return FALSE;
- }
- }
- else
- {
- if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc))
- return FALSE;
- }
- }
-
- if (pargs != NULL)
- (*pargs)[count] = DEBUG_TYPE_NULL;
-
- if (**pp == 'e')
- {
- if (pargs != NULL)
- *pvarargs = TRUE;
- ++*pp;
- }
-
- return TRUE;
-}
-
-/* Demangle a single argument. */
-
-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;
-
- start = *pp;
- if (! stab_demangle_type (minfo, pp,
- pargs == NULL ? (debug_type *) NULL : &type)
- || ! stab_demangle_remember_type (minfo, start, *pp - start))
- return FALSE;
-
- if (pargs != NULL)
- {
- if (type == DEBUG_TYPE_NULL)
- return FALSE;
-
- if (*pcount + 1 >= *palloc)
- {
- *palloc += 10;
- *pargs = ((debug_type *)
- xrealloc (*pargs, *palloc * sizeof **pargs));
- }
- (*pargs)[*pcount] = type;
- ++*pcount;
- }
-
- return TRUE;
-}
-
-/* Demangle a type. If the ptype argument is not NULL, *ptype is set
- to the newly allocated type. */
-
-static bfd_boolean
-stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
- debug_type *ptype)
-{
- const char *orig;
-
- orig = *pp;
-
- switch (**pp)
- {
- case 'P':
- case 'p':
- /* A pointer type. */
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_pointer_type (minfo->dhandle, *ptype);
- break;
-
- case 'R':
- /* A reference type. */
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_reference_type (minfo->dhandle, *ptype);
- break;
-
- case 'A':
- /* An array. */
- {
- unsigned long high;
-
- ++*pp;
- high = 0;
- while (**pp != '\0' && **pp != '_')
- {
- if (! ISDIGIT (**pp))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- high *= 10;
- high += **pp - '0';
- ++*pp;
- }
- if (**pp != '_')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- ++*pp;
-
- if (! stab_demangle_type (minfo, pp, ptype))
- 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);
- *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type,
- 0, high, FALSE);
- }
- }
- break;
-
- case 'T':
- /* A back reference to a remembered type. */
- {
- unsigned int i;
- const char *p;
-
- ++*pp;
- if (! stab_demangle_get_count (pp, &i))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- if (i >= minfo->typestring_count)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- p = minfo->typestrings[i].typestring;
- if (! stab_demangle_type (minfo, &p, ptype))
- return FALSE;
- }
- break;
-
- case 'F':
- /* A function. */
- {
- debug_type *args;
- bfd_boolean varargs;
-
- ++*pp;
- if (! stab_demangle_args (minfo, pp,
- (ptype == NULL
- ? (debug_type **) NULL
- : &args),
- (ptype == NULL
- ? (bfd_boolean *) NULL
- : &varargs)))
- 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;
- }
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
- varargs);
-
- }
- break;
-
- case 'M':
- case 'O':
- {
- bfd_boolean memberp, constp, volatilep;
- debug_type class_type = DEBUG_TYPE_NULL;
- debug_type *args;
- bfd_boolean varargs;
- unsigned int n;
- const char *name;
-
- memberp = **pp == 'M';
- constp = FALSE;
- volatilep = FALSE;
- args = NULL;
- varargs = FALSE;
-
- ++*pp;
- if (ISDIGIT (**pp))
- {
- 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;
- }
- else
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
-
- if (memberp)
- {
- if (**pp == 'C')
- {
- constp = TRUE;
- ++*pp;
- }
- else if (**pp == 'V')
- {
- volatilep = TRUE;
- ++*pp;
- }
- if (**pp != 'F')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- ++*pp;
- if (! stab_demangle_args (minfo, pp,
- (ptype == NULL
- ? (debug_type **) NULL
- : &args),
- (ptype == NULL
- ? (bfd_boolean *) NULL
- : &varargs)))
- return FALSE;
- }
-
- if (**pp != '_')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- ++*pp;
-
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
-
- if (ptype != NULL)
- {
- if (! memberp)
- *ptype = debug_make_offset_type (minfo->dhandle, class_type,
- *ptype);
- else
- {
- /* FIXME: We have no way to record constp or
- volatilep. */
- *ptype = debug_make_method_type (minfo->dhandle, *ptype,
- class_type, args, varargs);
- }
- }
- }
- break;
-
- case 'G':
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- break;
-
- case 'C':
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_const_type (minfo->dhandle, *ptype);
- break;
-
- case 'Q':
- {
- const char *hold;
-
- hold = *pp;
- if (! stab_demangle_qualified (minfo, pp, ptype))
- return FALSE;
- }
- break;
-
- default:
- if (! stab_demangle_fund_type (minfo, pp, ptype))
- return FALSE;
- break;
- }
-
- return TRUE;
-}
-
-/* Demangle a fundamental type. If the ptype argument is not NULL,
- *ptype is set to the newly allocated type. */
-
-static bfd_boolean
-stab_demangle_fund_type (struct stab_demangle_info *minfo, const char **pp,
- debug_type *ptype)
-{
- const char *orig;
- bfd_boolean constp, volatilep, unsignedp, signedp;
- bfd_boolean done;
-
- orig = *pp;
-
- constp = FALSE;
- volatilep = FALSE;
- unsignedp = FALSE;
- signedp = FALSE;
-
- done = FALSE;
- while (! done)
- {
- switch (**pp)
- {
- case 'C':
- constp = TRUE;
- ++*pp;
- break;
-
- case 'U':
- unsignedp = TRUE;
- ++*pp;
- break;
-
- case 'S':
- signedp = TRUE;
- ++*pp;
- break;
-
- case 'V':
- volatilep = TRUE;
- ++*pp;
- break;
-
- default:
- done = TRUE;
- break;
- }
- }
-
- switch (**pp)
- {
- case '\0':
- case '_':
- /* cplus_demangle permits this, but I don't know what it means. */
- stab_bad_demangle (orig);
- break;
-
- case 'v': /* void */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "void");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_void_type (minfo->dhandle);
- }
- ++*pp;
- break;
-
- case 'x': /* long long */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "long long unsigned int"
- : "long long int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp);
- }
- ++*pp;
- break;
-
- case 'l': /* long */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "long unsigned int"
- : "long int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
- }
- ++*pp;
- break;
-
- case 'i': /* int */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "unsigned int"
- : "int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
- }
- ++*pp;
- break;
-
- case 's': /* short */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "short unsigned int"
- : "short int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp);
- }
- ++*pp;
- break;
-
- case 'b': /* bool */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "bool");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_bool_type (minfo->dhandle, 4);
- }
- ++*pp;
- break;
-
- case 'c': /* char */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "unsigned char"
- : (signedp
- ? "signed char"
- : "char")));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp);
- }
- ++*pp;
- break;
-
- case 'w': /* wchar_t */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 2, TRUE);
- }
- ++*pp;
- break;
-
- case 'r': /* long double */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "long double");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_float_type (minfo->dhandle, 8);
- }
- ++*pp;
- break;
-
- case 'd': /* double */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "double");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_float_type (minfo->dhandle, 8);
- }
- ++*pp;
- break;
-
- case 'f': /* float */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "float");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_float_type (minfo->dhandle, 4);
- }
- ++*pp;
- break;
-
- case 'G':
- ++*pp;
- if (! ISDIGIT (**pp))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- /* Fall through. */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- const char *hold;
-
- if (! stab_demangle_class (minfo, pp, &hold))
- 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
- undefined types are tagged types. */
- *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
- hold, *pp - hold,
- DEBUG_KIND_ILLEGAL);
- if (*ptype == DEBUG_TYPE_NULL)
- return FALSE;
- }
- }
- }
- break;
-
- case 't':
- {
- 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;
- }
-
- if (ptype != NULL)
- {
- if (constp)
- *ptype = debug_make_const_type (minfo->dhandle, *ptype);
- if (volatilep)
- *ptype = debug_make_volatile_type (minfo->dhandle, *ptype);
- }
-
- return TRUE;
-}
-
-/* Remember a type string in a demangled string. */
-
-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->typestring_alloc += 10;
- minfo->typestrings = ((struct stab_demangle_typestring *)
- xrealloc (minfo->typestrings,
- (minfo->typestring_alloc
- * sizeof *minfo->typestrings)));
- }
-
- minfo->typestrings[minfo->typestring_count].typestring = p;
- minfo->typestrings[minfo->typestring_count].len = (unsigned int) len;
- ++minfo->typestring_count;
-
- return TRUE;
-}
-
-/* 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;
- }
- }
-}