summaryrefslogtreecommitdiff
path: root/binutils/stabs.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/stabs.c')
-rw-r--r--binutils/stabs.c5209
1 files changed, 0 insertions, 5209 deletions
diff --git a/binutils/stabs.c b/binutils/stabs.c
deleted file mode 100644
index 53e1070c8bc..00000000000
--- a/binutils/stabs.c
+++ /dev/null
@@ -1,5209 +0,0 @@
-/* stabs.c -- Parse stabs debugging information
- Copyright (C) 1995, 1996, 1997, 1998, 1999 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., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, 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 <ctype.h>
-
-#include "bfd.h"
-#include "bucomm.h"
-#include "libiberty.h"
-#include "demangle.h"
-#include "debug.h"
-#include "budbg.h"
-
-/* Meaningless definition needs by aout64.h. FIXME. */
-#define BYTES_IN_WORD 4
-
-#include "aout/aout64.h"
-#include "aout/stab_gnu.h"
-
-#ifndef DIR_SEPARATOR
-#ifdef _WIN32
-#define DIR_SEPARATOR '\\'
-#else
-#define DIR_SEPARATOR '/'
-#endif
-#endif
-
-/* 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. */
- 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. */
- 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. */
- 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. */
- 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 PARAMS ((const char *, int));
-static bfd_vma parse_number PARAMS ((const char **, boolean *));
-static void bad_stab PARAMS ((const char *));
-static void warn_stab PARAMS ((const char *, const char *));
-static boolean parse_stab_string
- PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *));
-static debug_type parse_stab_type
- PARAMS ((PTR, struct stab_handle *, const char *, const char **,
- debug_type **));
-static boolean parse_stab_type_number
- PARAMS ((const char **, int *));
-static debug_type parse_stab_range_type
- PARAMS ((PTR, struct stab_handle *, const char *, const char **,
- const int *));
-static debug_type parse_stab_sun_builtin_type PARAMS ((PTR, const char **));
-static debug_type parse_stab_sun_floating_type
- PARAMS ((PTR, const char **));
-static debug_type parse_stab_enum_type PARAMS ((PTR, const char **));
-static debug_type parse_stab_struct_type
- PARAMS ((PTR, struct stab_handle *, const char *, const char **, boolean,
- const int *));
-static boolean parse_stab_baseclasses
- PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **));
-static boolean parse_stab_struct_fields
- PARAMS ((PTR, struct stab_handle *, const char **, debug_field **,
- boolean *));
-static boolean parse_stab_cpp_abbrev
- PARAMS ((PTR, struct stab_handle *, const char **, debug_field *));
-static boolean parse_stab_one_struct_field
- PARAMS ((PTR, struct stab_handle *, const char **, const char *,
- debug_field *, boolean *));
-static boolean parse_stab_members
- PARAMS ((PTR, struct stab_handle *, const char *, const char **,
- const int *, debug_method **));
-static debug_type parse_stab_argtypes
- PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *,
- debug_type, const char *, boolean, boolean, const char **));
-static boolean parse_stab_tilde_field
- PARAMS ((PTR, struct stab_handle *, const char **, const int *,
- debug_type *, boolean *));
-static debug_type parse_stab_array_type
- PARAMS ((PTR, struct stab_handle *, const char **, boolean));
-static void push_bincl PARAMS ((struct stab_handle *, const char *, bfd_vma));
-static const char *pop_bincl PARAMS ((struct stab_handle *));
-static boolean find_excl
- PARAMS ((struct stab_handle *, const char *, bfd_vma));
-static boolean stab_record_variable
- PARAMS ((PTR, struct stab_handle *, const char *, debug_type,
- enum debug_var_kind, bfd_vma));
-static boolean stab_emit_pending_vars PARAMS ((PTR, struct stab_handle *));
-static debug_type *stab_find_slot
- PARAMS ((struct stab_handle *, const int *));
-static debug_type stab_find_type
- PARAMS ((PTR, struct stab_handle *, const int *));
-static boolean stab_record_type
- PARAMS ((PTR, struct stab_handle *, const int *, debug_type));
-static debug_type stab_xcoff_builtin_type
- PARAMS ((PTR, struct stab_handle *, int));
-static debug_type stab_find_tagged_type
- PARAMS ((PTR, struct stab_handle *, const char *, int,
- enum debug_type_kind));
-static debug_type *stab_demangle_argtypes
- PARAMS ((PTR, struct stab_handle *, const char *, boolean *));
-
-/* Save a string in memory. */
-
-static char *
-savestring (start, len)
- 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 (pp, poverflow)
- const char **pp;
- 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;
- boolean neg;
- int base;
- bfd_vma over, lastdig;
- 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 ((unsigned char) d))
- d -= '0';
- else if (isupper ((unsigned char) d))
- d -= 'A';
- else if (islower ((unsigned char) 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 (p)
- const char *p;
-{
- fprintf (stderr, _("Bad stab: %s\n"), p);
-}
-
-/* Warn about something in a stab string. */
-
-static void
-warn_stab (p, err)
- const char *p;
- const char *err;
-{
- fprintf (stderr, _("Warning: %s: %s\n"), err, p);
-}
-
-/* Create a handle to parse stabs symbols with. */
-
-/*ARGSUSED*/
-PTR
-start_stab (dhandle, abfd, sections, syms, symcount)
- PTR dhandle ATTRIBUTE_UNUSED;
- bfd *abfd;
- 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 (PTR) ret;
-}
-
-/* When we have processed all the stabs information, we need to go
- through and fill in all the undefined tags. */
-
-boolean
-finish_stab (dhandle, handle)
- PTR dhandle;
- PTR handle;
-{
- 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. */
-
-boolean
-parse_stab (dhandle, handle, type, desc, value, string)
- PTR dhandle;
- PTR 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 ( (string[0] == '/')
- || (string[0] == DIR_SEPARATOR)
- || ( (DIR_SEPARATOR == '\\')
- && (string[1] == ':')
- && ( (string[2] == DIR_SEPARATOR)
- || (string[2] == '/'))))
- 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->function_start_offset))
- 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:
- break;
- }
-
- return true;
-}
-
-/* Parse the stabs string. */
-
-static boolean
-parse_stab_string (dhandle, info, stabtype, desc, value, string)
- PTR dhandle;
- struct stab_handle *info;
- int stabtype;
- int desc;
- bfd_vma value;
- const char *string;
-{
- const char *p;
- char *name;
- int type;
- debug_type dtype;
- boolean synonym;
- 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 ((unsigned char) *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 (dhandle, info, typename, pp, slotp)
- PTR dhandle;
- struct stab_handle *info;
- const char *typename;
- const char **pp;
- debug_type **slotp;
-{
- const char *orig;
- int typenums[2];
- int size;
- 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 ((unsigned char) **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 ((unsigned char) *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);
- 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;
- 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 ((PTR) 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 false;
- }
-
- 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 boolean
-parse_stab_type_number (pp, typenums)
- const char **pp;
- int *typenums;
-{
- const char *orig;
-
- orig = *pp;
-
- if (**pp != '(')
- {
- typenums[0] = 0;
- typenums[1] = (int) parse_number (pp, (boolean *) NULL);
- }
- else
- {
- ++*pp;
- typenums[0] = (int) parse_number (pp, (boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
- typenums[1] = (int) parse_number (pp, (boolean *) NULL);
- if (**pp != ')')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
- }
-
- return true;
-}
-
-/* Parse a range type. */
-
-static debug_type
-parse_stab_range_type (dhandle, info, typename, pp, typenums)
- PTR dhandle;
- struct stab_handle *info;
- const char *typename;
- const char **pp;
- const int *typenums;
-{
- const char *orig;
- int rangenums[2];
- boolean self_subrange;
- debug_type index_type;
- const char *s2, *s3;
- bfd_signed_vma n2, n3;
- 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_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 (dhandle, pp)
- PTR dhandle;
- const char **pp;
-{
- const char *orig;
- 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, (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, (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, (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 (dhandle, pp)
- PTR 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, (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, (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 (dhandle, pp)
- PTR 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, (boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
-
- if (n + 1 >= alloc)
- {
- alloc += 10;
- names = ((const char **)
- xrealloc ((PTR) names, alloc * sizeof *names));
- values = ((bfd_signed_vma *)
- xrealloc ((PTR) 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 the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
- *PP will point to "4a:1,0,32;;". */
-
-static debug_type
-parse_stab_struct_type (dhandle, info, tagname, pp, structp, typenums)
- PTR dhandle;
- struct stab_handle *info;
- const char *tagname;
- const char **pp;
- boolean structp;
- const int *typenums;
-{
- const char *orig;
- bfd_vma size;
- debug_baseclass *baseclasses;
- debug_field *fields;
- boolean statics;
- debug_method *methods;
- debug_type vptrbase;
- boolean ownvptr;
-
- orig = *pp;
-
- /* Get the size. */
- size = parse_number (pp, (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 boolean
-parse_stab_baseclasses (dhandle, info, pp, retp)
- PTR 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, (boolean *) NULL);
-
- if (**pp != ',')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
-
- classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp));
-
- for (i = 0; i < c; i++)
- {
- 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, (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 boolean
-parse_stab_struct_fields (dhandle, info, pp, retp, staticsp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- debug_field **retp;
- 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 ((PTR) 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 boolean
-parse_stab_cpp_abbrev (dhandle, info, pp, retp)
- PTR 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, (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 boolean
-parse_stab_one_struct_field (dhandle, info, pp, p, retp, staticsp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- const char *p;
- debug_field *retp;
- boolean *staticsp;
-{
- 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, (boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
-
- bitsize = parse_number (pp, (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 boolean
-parse_stab_members (dhandle, info, tagname, pp, typenums, retp)
- PTR dhandle;
- struct stab_handle *info;
- const char *tagname;
- const char **pp;
- const int *typenums;
- debug_method **retp;
-{
- 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 wierd 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;
- boolean stub;
- char *argtypes;
- enum debug_visibility visibility;
- boolean constp, volatilep, staticp;
- bfd_vma voffset;
- debug_type context;
- const char *physname;
- 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, (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 ((PTR) 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 ((PTR) 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 (dhandle, info, class_type, fieldname, tagname,
- return_type, argtypes, constp, volatilep, pphysname)
- PTR dhandle;
- struct stab_handle *info;
- debug_type class_type;
- const char *fieldname;
- const char *tagname;
- debug_type return_type;
- const char *argtypes;
- boolean constp;
- boolean volatilep;
- const char **pphysname;
-{
- boolean is_full_physname_constructor;
- boolean is_constructor;
- boolean is_destructor;
- debug_type *args;
- boolean varargs;
-
- /* Constructors are sometimes handled specially. */
- is_full_physname_constructor = ((argtypes[0] == '_'
- && argtypes[1] == '_'
- && (isdigit ((unsigned char) 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);
-
- if (is_destructor || is_full_physname_constructor)
- *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);
- }
-
- 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);
- 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 boolean
-parse_stab_tilde_field (dhandle, info, pp, typenums, retvptrbase, retownvptr)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- const int *typenums;
- debug_type *retvptrbase;
- boolean *retownvptr;
-{
- 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 (dhandle, info, pp, stringp)
- PTR dhandle;
- struct stab_handle *info;
- const char **pp;
- boolean stringp;
-{
- const char *orig;
- const char *p;
- int typenums[2];
- debug_type index_type;
- 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 false;
- 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 false;
- }
- *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 ((unsigned char) **pp) && **pp != '-')
- {
- ++*pp;
- adjustable = true;
- }
-
- lower = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
-
- if (! isdigit ((unsigned char) **pp) && **pp != '-')
- {
- ++*pp;
- adjustable = true;
- }
-
- upper = (bfd_signed_vma) parse_number (pp, (boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return false;
- }
- ++*pp;
-
- element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (element_type == DEBUG_TYPE_NULL)
- return false;
-
- 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 (info, name, hash)
- 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 ((PTR) 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 (info)
- 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 boolean
-find_excl (info, name, hash)
- struct stab_handle *info;
- const char *name;
- bfd_vma hash;
-{
- struct bincl_file *l;
-
- ++info->files;
- info->file_types = ((struct stab_types **)
- xrealloc ((PTR) info->file_types,
- (info->files
- * sizeof *info->file_types)));
-
- for (l = info->bincl_list; l != NULL; l = l->next)
- if (l->hash == hash && strcmp (l->name, name) == 0)
- break;
- if (l == NULL)
- {
- warn_stab (name, _("Undefined N_EXCL"));
- info->file_types[info->files - 1] = NULL;
- return true;
- }
-
- info->file_types[info->files - 1] = l->file_types;
-
- return true;
-}
-
-/* Handle a variable definition. gcc emits variable definitions for a
- block before the N_LBRAC, so we must hold onto them until we see
- it. The SunPRO compiler emits variable definitions after the
- N_LBRAC, so we can call debug_record_variable immediately. */
-
-static boolean
-stab_record_variable (dhandle, info, name, type, kind, val)
- PTR dhandle;
- struct stab_handle *info;
- const char *name;
- debug_type type;
- enum debug_var_kind kind;
- bfd_vma val;
-{
- 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 boolean
-stab_emit_pending_vars (dhandle, info)
- PTR 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 (info, typenums)
- 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 (dhandle, info, typenums)
- PTR 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 boolean
-stab_record_type (dhandle, info, typenums, type)
- PTR 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 (dhandle, info, typenum)
- PTR 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 (dhandle, info, p, len, kind)
- PTR 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. */
- PTR dhandle;
- /* The stab information handle. */
- struct stab_handle *info;
- /* The array of arguments we are building. */
- debug_type *args;
- /* Whether the method takes a variable number of arguments. */
- boolean varargs;
- /* 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 PARAMS ((const char *));
-static unsigned int stab_demangle_count PARAMS ((const char **));
-static boolean stab_demangle_get_count
- PARAMS ((const char **, unsigned int *));
-static boolean stab_demangle_prefix
- PARAMS ((struct stab_demangle_info *, const char **));
-static boolean stab_demangle_function_name
- PARAMS ((struct stab_demangle_info *, const char **, const char *));
-static boolean stab_demangle_signature
- PARAMS ((struct stab_demangle_info *, const char **));
-static boolean stab_demangle_qualified
- PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
-static boolean stab_demangle_template
- PARAMS ((struct stab_demangle_info *, const char **, char **));
-static boolean stab_demangle_class
- PARAMS ((struct stab_demangle_info *, const char **, const char **));
-static boolean stab_demangle_args
- PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
- boolean *));
-static boolean stab_demangle_arg
- PARAMS ((struct stab_demangle_info *, const char **, debug_type **,
- unsigned int *, unsigned int *));
-static boolean stab_demangle_type
- PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
-static boolean stab_demangle_fund_type
- PARAMS ((struct stab_demangle_info *, const char **, debug_type *));
-static boolean stab_demangle_remember_type
- PARAMS ((struct stab_demangle_info *, const char *, int));
-
-/* Warn about a bad demangling. */
-
-static void
-stab_bad_demangle (s)
- const char *s;
-{
- fprintf (stderr, _("bad mangled name `%s'\n"), s);
-}
-
-/* Get a count from a stab string. */
-
-static unsigned int
-stab_demangle_count (pp)
- const char **pp;
-{
- unsigned int count;
-
- count = 0;
- while (isdigit ((unsigned char) **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 boolean
-stab_demangle_get_count (pp, pi)
- const char **pp;
- unsigned int *pi;
-{
- if (! isdigit ((unsigned char) **pp))
- return false;
-
- *pi = **pp - '0';
- ++*pp;
- if (isdigit ((unsigned char) **pp))
- {
- unsigned int count;
- const char *p;
-
- count = *pi;
- p = *pp;
- do
- {
- count *= 10;
- count += *p - '0';
- ++p;
- }
- while (isdigit ((unsigned char) *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 (dhandle, info, physname, pvarargs)
- PTR dhandle;
- struct stab_handle *info;
- const char *physname;
- boolean *pvarargs;
-{
- struct stab_demangle_info minfo;
-
- 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))
- 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 boolean
-stab_demangle_prefix (minfo, pp)
- struct stab_demangle_info *minfo;
- const char **pp;
-{
- const char *scan;
- unsigned int i;
-
- /* cplus_demangle checks for global constructors and destructors,
- but we can't see them in mangled argument types. */
-
- /* Look for `__'. */
- scan = *pp;
- do
- {
- 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 ((unsigned char) 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 ((unsigned char) 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 boolean
-stab_demangle_function_name (minfo, pp, scan)
- 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 boolean
-stab_demangle_signature (minfo, pp)
- struct stab_demangle_info *minfo;
- const char **pp;
-{
- const char *orig;
- 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 boolean
-stab_demangle_qualified (minfo, pp, ptype)
- 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 ((unsigned char) *p) || *p == '0')
- {
- stab_bad_demangle (orig);
- return false;
- }
- qualifiers = atoi (p);
- while (isdigit ((unsigned char) *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 boolean
-stab_demangle_template (minfo, pp, pname)
- 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;
- boolean pointerp, realp, integralp, charp, boolp;
- 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 ((unsigned char) **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 ((unsigned char) **pp))
- ++*pp;
- if (**pp == '.')
- {
- ++*pp;
- while (isdigit ((unsigned char) **pp))
- ++*pp;
- }
- if (**pp == 'e')
- {
- ++*pp;
- while (isdigit ((unsigned char) **pp))
- ++*pp;
- }
- }
- else if (pointerp)
- {
- unsigned int len;
-
- if (! stab_demangle_get_count (pp, &len))
- {
- 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;
- char *from, *to;
-
- s1 = savestring (orig, *pp - orig);
-
- s2 = concat ("NoSuchStrinG__", s1, (const char *) NULL);
-
- free (s1);
-
- s3 = cplus_demangle (s2, DMGL_ANSI);
-
- free (s2);
-
- if (s3 != NULL)
- s4 = strstr (s3, "::NoSuchStrinG");
- if (s3 == NULL || s4 == NULL)
- {
- stab_bad_demangle (orig);
- if (s3 != NULL)
- free (s3);
- return false;
- }
-
- /* Eliminating all spaces, except those between > characters,
- makes it more likely that the demangled name will match the
- name which g++ used as the structure name. */
- for (from = to = s3; from != s4; ++from)
- if (*from != ' '
- || (from[1] == '>' && from > s3 && from[-1] == '>'))
- *to++ = *from;
-
- *pname = savestring (s3, to - s3);
-
- free (s3);
- }
-
- return true;
-}
-
-/* Demangle a class name. */
-
-static boolean
-stab_demangle_class (minfo, pp, pstart)
- struct stab_demangle_info *minfo 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 boolean
-stab_demangle_args (minfo, pp, pargs, pvarargs)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type **pargs;
- 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 boolean
-stab_demangle_arg (minfo, pp, pargs, pcount, palloc)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type **pargs;
- unsigned int *pcount;
- unsigned int *palloc;
-{
- 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 boolean
-stab_demangle_type (minfo, pp, ptype)
- 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 ((unsigned char) **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;
- boolean varargs;
-
- ++*pp;
- if (! stab_demangle_args (minfo, pp,
- (ptype == NULL
- ? (debug_type **) NULL
- : &args),
- (ptype == NULL
- ? (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':
- {
- boolean memberp, constp, volatilep;
- debug_type class_type = DEBUG_TYPE_NULL;
- debug_type *args;
- boolean varargs;
- unsigned int n;
- const char *name;
-
- memberp = **pp == 'M';
- constp = false;
- volatilep = false;
- args = NULL;
- varargs = false;
-
- ++*pp;
- if (isdigit ((unsigned char) **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
- ? (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 boolean
-stab_demangle_fund_type (minfo, pp, ptype)
- struct stab_demangle_info *minfo;
- const char **pp;
- debug_type *ptype;
-{
- const char *orig;
- boolean constp, volatilep, unsignedp, signedp;
- 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 ((unsigned char) **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 boolean
-stab_demangle_remember_type (minfo, p, len)
- 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;
-}