/* Support routines for decoding "stabs" debugging information format.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993
Free Software Foundation, Inc.
This file is part of GDB.
#include "obstack.h"
#include "symtab.h"
#include "gdbtypes.h"
-#include "symfile.h" /* Needed for "struct complaint" */
+#include "symfile.h"
#include "objfiles.h"
#include "aout/stab_gnu.h" /* We always use GNU stabs, not native */
#include "buildsym.h"
+#include "complaints.h"
+#include "demangle.h"
/* Ask stabsread.h to define the vars it normally declares `extern'. */
#define EXTERN /**/
static struct type *
read_enum_type PARAMS ((char **, struct type *, struct objfile *));
+static struct type *
+rs6000_builtin_type PARAMS ((int));
+
static int
read_member_functions PARAMS ((struct field_info *, char **, struct type *,
struct objfile *));
struct complaint reg_value_complaint =
{"register number too large in symbol %s", 0, 0};
+struct complaint vtbl_notfound_complaint =
+ {"virtual function table pointer not found when defining class `%s'", 0, 0};
+
+struct complaint unrecognized_cplus_name_complaint =
+ {"Unknown C++ symbol name `%s'", 0, 0};
+
+struct complaint rs6000_builtin_complaint =
+ {"Unknown builtin type %d", 0, 0};
+
struct complaint stabs_general_complaint =
{"%s", 0, 0};
if (filenum == 0)
{
+ if (index < 0)
+ {
+ /* Caller wants address of address of type. We think
+ that negative (rs6k builtin) types will never appear as
+ "lvalues", (nor should they), so we stuff the real type
+ pointer into a temp, and return its address. If referenced,
+ this will do the right thing. */
+ static struct type *temp_type;
+
+ temp_type = rs6000_builtin_type(index);
+ return &temp_type;
+ }
+
/* Type is defined outside of header files.
Find it in this object file's type vector. */
if (index >= type_vector_length)
goto normal;
default:
- abort ();
+ complain (unrecognized_cplus_name_complaint, string);
+ goto normal; /* Do *something* with it */
}
}
else
{
normal:
+ SYMBOL_LANGUAGE (sym) = current_subfile -> language;
SYMBOL_NAME (sym) = (char *)
obstack_alloc (&objfile -> symbol_obstack, ((p - string) + 1));
/* Open-coded bcopy--saves function call time. */
+ /* FIXME: Does it really? Try replacing with simple strcpy and
+ try it on an executable with a large symbol table. */
{
register char *p1 = string;
register char *p2 = SYMBOL_NAME (sym);
}
*p2++ = '\0';
}
+
+ /* If this symbol is from a C++ compilation, then attempt to cache the
+ demangled form for future reference. This is a typical time versus
+ space tradeoff, that was decided in favor of time because it sped up
+ C++ symbol lookups by a factor of about 20. */
+
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
}
p++;
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
if (SYMBOL_VALUE (sym) >= NUM_REGS)
{
- complain (®_value_complaint, SYMBOL_NAME (sym));
+ complain (®_value_complaint, SYMBOL_SOURCE_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
}
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
if (SYMBOL_VALUE (sym) >= NUM_REGS)
{
- complain (®_value_complaint, SYMBOL_NAME (sym));
+ complain (®_value_complaint, SYMBOL_SOURCE_NAME (sym));
SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
}
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
if (synonym)
{
+ /* Clone the sym and then modify it. */
register struct symbol *typedef_sym = (struct symbol *)
obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
- memset (typedef_sym, 0, sizeof (struct symbol));
- SYMBOL_NAME (typedef_sym) = SYMBOL_NAME (sym);
- SYMBOL_TYPE (typedef_sym) = SYMBOL_TYPE (sym);
-
+ *typedef_sym = *sym;
SYMBOL_CLASS (typedef_sym) = LOC_TYPEDEF;
SYMBOL_VALUE (typedef_sym) = valu;
SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
error_type (pp)
char **pp;
{
- complain (&error_type_complaint, 0);
+ complain (&error_type_complaint);
while (1)
{
/* Skip to end of symbol. */
/* Copy the prefix. */
from = prefix;
- while (*to++ = *from++)
+ while ((*to++ = *from++) != '\0')
;
to--;
if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
&& SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
&& (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
- && !strcmp (SYMBOL_NAME (sym), type_name_only))
+ && STREQ (SYMBOL_NAME (sym), type_name_only))
{
obstack_free (&objfile -> type_obstack, type_name);
type = SYMBOL_TYPE (sym);
}
case '-': /* RS/6000 built-in type */
- (*pp)--;
- type = builtin_type (pp); /* (in xcoffread.c) */
- goto after_digits;
-
case '0':
case '1':
case '2':
(*pp)--;
read_type_number (pp, xtypenums);
type = *dbx_lookup_type (xtypenums);
- /* fall through */
-
- after_digits:
if (type == 0)
type = lookup_fundamental_type (objfile, FT_VOID);
if (typenums[0] != -1)
(*pp)++;
return_type = read_type (pp, objfile);
if (*(*pp)++ != ';')
- complain (&invalid_member_complaint, (char *) symnum);
+ complain (&invalid_member_complaint, symnum);
type = allocate_stub_method (return_type);
if (typenums[0] != -1)
*dbx_lookup_type (typenums) = type;
return type;
}
\f
+/* RS/6000 xlc/dbx combination uses a set of builtin types, starting from -1.
+ Return the proper type node for a given builtin type number. */
+
+static struct type *
+rs6000_builtin_type (typenum)
+ int typenum;
+{
+ /* default types are defined in dbxstclass.h. */
+ switch (-typenum) {
+ case 1:
+ return lookup_fundamental_type (current_objfile, FT_INTEGER);
+ case 2:
+ return lookup_fundamental_type (current_objfile, FT_CHAR);
+ case 3:
+ return lookup_fundamental_type (current_objfile, FT_SHORT);
+ case 4:
+ return lookup_fundamental_type (current_objfile, FT_LONG);
+ case 5:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+ case 6:
+ return lookup_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+ case 7:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+ case 8:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+ case 9:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+ case 10:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
+ case 11:
+ return lookup_fundamental_type (current_objfile, FT_VOID);
+ case 12:
+ return lookup_fundamental_type (current_objfile, FT_FLOAT);
+ case 13:
+ return lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+ case 14:
+ return lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
+ case 15:
+ /* requires a builtin `integer' */
+ return lookup_fundamental_type (current_objfile, FT_INTEGER);
+ case 16:
+ return lookup_fundamental_type (current_objfile, FT_BOOLEAN);
+ case 17:
+ /* requires builtin `short real' */
+ return lookup_fundamental_type (current_objfile, FT_FLOAT);
+ case 18:
+ /* requires builtin `real' */
+ return lookup_fundamental_type (current_objfile, FT_FLOAT);
+ default:
+ complain (rs6000_builtin_complaint, typenum);
+ return NULL;
+ }
+}
+\f
/* This page contains subroutines of read_type. */
#define VISIBILITY_PRIVATE '0' /* Stabs character for private field */
if (**pp != ':')
{
/* Invalid symtab info for member function. */
- return (0);
+ return 0;
}
}
else
case '.':
break;
default:
- complain (&const_vol_complaint, (char *) (long) **pp);
+ complain (&const_vol_complaint, **pp);
break;
}
new_sublist -> fn_field.fcontext = look_ahead_type;
if (**pp != ';')
{
- return (0);
+ return 0;
}
else
{
default:
/* error */
- complain (&member_fn_complaint, (char *) (long) (*pp)[-1]);
+ complain (&member_fn_complaint, (*pp)[-1]);
/* Fall through into normal member function. */
case '.':
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
- return (1);
+ return 1;
}
/* Special GNU C++ name.
register char *p;
const char *prefix;
char *name;
+ char cpp_abbrev;
struct type *context;
p = *pp;
if (*++p == 'v')
{
name = NULL;
- switch (*++p)
- {
- case 'f':
- prefix = vptr_name;
- break;
- case 'b':
- prefix = vb_name;
- break;
- default:
- complain (&invalid_cpp_abbrev_complaint, *pp);
- prefix = "INVALID_C++_ABBREV";
- break;
- }
+ cpp_abbrev = *++p;
+
*pp = p + 1;
/* At this point, *pp points to something like "22:23=*22...",
type, find it's name, and construct the field name. */
context = read_type (pp, objfile);
- name = type_name_no_tag (context);
- if (name == NULL)
+
+ switch (cpp_abbrev)
{
- complain (&invalid_cpp_type_complaint, (char *) symnum);
- name = "FOO";
+ case 'f': /* $vf -- a virtual function table pointer */
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack, vptr_name, "", "");
+ break;
+
+ case 'b': /* $vb -- a virtual bsomethingorother */
+ name = type_name_no_tag (context);
+ if (name == NULL)
+ {
+ complain (&invalid_cpp_type_complaint, symnum);
+ name = "FOO";
+ }
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack, vb_name, name, "");
+ break;
+
+ default:
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack,
+ "INVALID_CPLUSPLUS_ABBREV", "", "");
+ break;
}
- fip -> list -> field.name =
- obconcat (&objfile -> type_obstack, prefix, name, "");
/* At this point, *pp points to the ':'. Skip it and read the
field type. */
{
complain (&invalid_cpp_abbrev_complaint, *pp);
}
- fip -> list -> field.type = read_type (pp, objfile);
+ fip->list->field.type = read_type (pp, objfile);
(*pp)++; /* Skip the comma. */
- fip -> list -> field.bitpos = read_number (pp, ';');
+ fip->list->field.bitpos = read_number (pp, ';');
/* This field is unpacked. */
- fip -> list -> field.bitsize = 0;
- fip -> list -> visibility = VISIBILITY_PRIVATE;
+ fip->list->field.bitsize = 0;
+ fip->list->visibility = VISIBILITY_PRIVATE;
}
else if (*p == '_')
{
stuff. */
if (fip -> list -> field.bitpos == 0 && fip -> list -> field.bitsize == 0)
{
- complain (&dbx_class_complaint, 0);
+ complain (&dbx_class_complaint);
/* Ignore this field. */
fip -> list = fip -> list -> next;
}
partially constructed entry which we now scrub. */
fip -> list = fip -> list -> next;
}
- return (1);
+ return 1;
}
/* The stabs for C++ derived classes contain baseclass information which
if (**pp != '!')
{
- return (1);
+ return 1;
}
else
{
break;
default:
/* Bad visibility format. */
- return (0);
+ return 0;
}
new -> visibility = *(*pp)++;
break;
default:
/* Bad visibility format. */
- return (0);
+ return 0;
}
/* The remaining value is the bit offset of the portion of the object
/* skip trailing ';' and bump count of number of fields seen */
(*pp)++;
}
- return (1);
+ return 1;
}
+/* 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 int
read_tilde_fields (fip, pp, type, objfile)
struct field_info *fip;
/* Read either a '%' or the final ';'. */
if (*(*pp)++ == '%')
{
- /* We'd like to be able to derive the vtable pointer field
- from the type information, but when it's inherited, that's
- hard. A reason it's hard is because we may read in the
- info about a derived class before we read in info about
- the base class that provides the vtable pointer field.
- Once the base info has been read, we could fill in the info
- for the derived classes, but for the fact that by then,
- we don't remember who needs what. */
-
-#if 0
- int predicted_fieldno = -1;
-#endif
-
- /* Now we must record the virtual function table pointer's
- field information. */
+ /* The next number is the type number of the base class
+ (possibly our own class) which supplies the vtable for
+ this class. Parse it out, and search that class to find
+ its vtable pointer, and install those into TYPE_VPTR_BASETYPE
+ and TYPE_VPTR_FIELDNO. */
struct type *t;
int i;
-#if 0
- {
- /* In version 2, we derive the vfield ourselves. */
- for (n = 0; n < TYPE_NFIELDS (type); n++)
- {
- if (! strncmp (TYPE_FIELD_NAME (type, n), vptr_name,
- sizeof (vptr_name) - 1))
- {
- predicted_fieldno = n;
- break;
- }
- }
- if (predicted_fieldno < 0)
- {
- for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
- {
- if (! TYPE_FIELD_VIRTUAL (type, n)
- && TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, n)) >= 0)
- {
- predicted_fieldno =
- TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, n));
- break;
- }
- }
- }
- }
-#endif
-
t = read_type (pp, objfile);
p = (*pp)++;
while (*p != '\0' && *p != ';')
if (*p == '\0')
{
/* Premature end of symbol. */
- return (0);
+ return 0;
}
TYPE_VPTR_BASETYPE (type) = t;
- if (type == t)
+ if (type == t) /* Our own class provides vtbl ptr */
{
- if (TYPE_FIELD_NAME (t, TYPE_N_BASECLASSES (t)) == 0)
+ for (i = TYPE_NFIELDS (t) - 1;
+ i >= TYPE_N_BASECLASSES (t);
+ --i)
{
- /* FIXME-tiemann: what's this? */
-#if 0
- TYPE_VPTR_FIELDNO (type) = i = TYPE_N_BASECLASSES (t);
-#else
- error_type (pp);
-#endif
- }
- else
- {
- for (i = TYPE_NFIELDS (t) - 1;
- i >= TYPE_N_BASECLASSES (t);
- --i)
+ if (! strncmp (TYPE_FIELD_NAME (t, i), vptr_name,
+ sizeof (vptr_name) - 1))
{
- if (! strncmp (TYPE_FIELD_NAME (t, i), vptr_name,
- sizeof (vptr_name) - 1))
- {
- TYPE_VPTR_FIELDNO (type) = i;
- break;
- }
+ TYPE_VPTR_FIELDNO (type) = i;
+ goto gotit;
}
}
- if (i < 0)
- {
- /* Virtual function table field not found. */
- return (0);
- }
+ /* Virtual function table field not found. */
+ complain (vtbl_notfound_complaint, TYPE_NAME (type));
+ return 0;
}
else
{
TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
}
-#if 0
- if (TYPE_VPTR_FIELDNO (type) != predicted_fieldno)
- {
- error ("TYPE_VPTR_FIELDNO miscalculated");
- }
-#endif
-
+ gotit:
*pp = p + 1;
}
}
- return (1);
+ return 1;
}
static int
if (TYPE_CODE (TYPE_BASECLASS (type, n)) == TYPE_CODE_UNDEF)
{
/* @@ Memory leak on objfile -> type_obstack? */
- return (0);
+ return 0;
}
TYPE_NFN_FIELDS_TOTAL (type) +=
TYPE_NFN_FIELDS_TOTAL (TYPE_BASECLASS (type, n));
--n; /* Circumvent Sun3 compiler bug */
TYPE_FN_FIELDLISTS (type)[n] = fip -> fnlist -> fn_fieldlist;
}
- return (1);
+ return 1;
}
/* Create the vector of fields, and record how big it is.
}
fip -> list = fip -> list -> next;
}
- return (1);
+ return 1;
}
/* Read the description of a structure (or union type) and return an object
/* Now read the baseclasses, if any, read the regular C struct or C++
class member fields, attach the fields to the type, read the C++
member functions, attach them to the type, and then read any tilde
- fields. */
+ field (baseclass specifier for the class holding the main vtable). */
- if (!read_baseclasses (&fi, pp, type, objfile)
- || !read_struct_fields (&fi, pp, type, objfile)
- || !attach_fields_to_type (&fi, type, objfile)
- || !read_member_functions (&fi, pp, type, objfile)
- || !attach_fn_fields_to_type (&fi, type)
- || !read_tilde_fields (&fi, pp, type, objfile))
+ if (!read_baseclasses (&fi, pp, type, objfile))
+ {
+ do_cleanups (back_to);
+ return (error_type (pp));
+ }
+ if (!read_struct_fields (&fi, pp, type, objfile))
+ {
+ do_cleanups (back_to);
+ return (error_type (pp));
+ }
+ if (!attach_fields_to_type (&fi, type, objfile))
+ {
+ do_cleanups (back_to);
+ return (error_type (pp));
+ }
+ if (!read_member_functions (&fi, pp, type, objfile))
+ {
+ do_cleanups (back_to);
+ return (error_type (pp));
+ }
+ if (!attach_fn_fields_to_type (&fi, type))
+ {
+ do_cleanups (back_to);
+ return (error_type (pp));
+ }
+ if (!read_tilde_fields (&fi, pp, type, objfile))
{
do_cleanups (back_to);
return (error_type (pp));
upper = -1;
}
- type = create_array_type (type, element_type, index_type, lower, upper);
+ range_type =
+ create_range_type ((struct type *) NULL, index_type, lower, upper);
+ type = create_array_type (type, element_type, range_type);
/* If we have an array whose element type is not yet known, but whose
bounds *are* known, record it to be adjusted at the end of the file. */
obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
SYMBOL_NAME (sym) = name;
+ SYMBOL_LANGUAGE (sym) = current_subfile -> language;
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
SYMBOL_VALUE (sym) = n;
/* This screws up perfectly good C programs with enums. FIXME. */
/* Is this Modula-2's BOOLEAN type? Flag it as such if so. */
if(TYPE_NFIELDS(type) == 2 &&
- ((!strcmp(TYPE_FIELD_NAME(type,0),"TRUE") &&
- !strcmp(TYPE_FIELD_NAME(type,1),"FALSE")) ||
- (!strcmp(TYPE_FIELD_NAME(type,1),"TRUE") &&
- !strcmp(TYPE_FIELD_NAME(type,0),"FALSE"))))
+ ((STREQ(TYPE_FIELD_NAME(type,0),"TRUE") &&
+ STREQ(TYPE_FIELD_NAME(type,1),"FALSE")) ||
+ (STREQ(TYPE_FIELD_NAME(type,1),"TRUE") &&
+ STREQ(TYPE_FIELD_NAME(type,0),"FALSE"))))
TYPE_CODE(type) = TYPE_CODE_BOOL;
#endif
int n2bits, n3bits;
int self_subrange;
struct type *result_type;
+ struct type *index_type;
/* First comes a type we are a subrange of.
In C it is usually 0, 1 or the type being defined. */
if (self_subrange)
return error_type (pp);
- result_type = alloc_type (objfile);
-
- TYPE_CODE (result_type) = TYPE_CODE_RANGE;
-
- TYPE_TARGET_TYPE (result_type) = *dbx_lookup_type(rangenums);
- if (TYPE_TARGET_TYPE (result_type) == 0) {
- complain (&range_type_base_complaint, (char *) rangenums[1]);
- TYPE_TARGET_TYPE (result_type) = lookup_fundamental_type (objfile, FT_INTEGER);
- }
-
- TYPE_NFIELDS (result_type) = 2;
- TYPE_FIELDS (result_type) = (struct field *)
- TYPE_ALLOC (result_type, 2 * sizeof (struct field));
- memset (TYPE_FIELDS (result_type), 0, 2 * sizeof (struct field));
- TYPE_FIELD_BITPOS (result_type, 0) = n2;
- TYPE_FIELD_BITPOS (result_type, 1) = n3;
-
- TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type));
+ index_type = *dbx_lookup_type (rangenums);
+ if (index_type == NULL)
+ {
+ complain (&range_type_base_complaint, rangenums[1]);
+ index_type = lookup_fundamental_type (objfile, FT_INTEGER);
+ }
- return result_type;
+ result_type = create_range_type ((struct type *) NULL, index_type, n2, n3);
+ return (result_type);
}
/* Read a number from the string pointed to by *PP.
&& SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
&& (TYPE_CODE (SYMBOL_TYPE (sym)) ==
TYPE_CODE (*type))
- && !strcmp (SYMBOL_NAME (sym), typename))
+ && STREQ (SYMBOL_NAME (sym), typename))
{
memcpy (*type, SYMBOL_TYPE (sym),
sizeof (struct type));
if (objfile->msymbols == 0) /* Beware the null file. */
return;
- for (msymbol = objfile -> msymbols; msymbol -> name != NULL; msymbol++)
+ for (msymbol = objfile -> msymbols; SYMBOL_NAME (msymbol) != NULL; msymbol++)
{
QUIT;
/* Get the hash index and check all the symbols
under that hash index. */
- hash = hashname (msymbol -> name);
+ hash = hashname (SYMBOL_NAME (msymbol));
for (sym = global_sym_chain[hash]; sym;)
{
- if (*(msymbol -> name) == SYMBOL_NAME (sym)[0]
- && !strcmp(msymbol -> name + 1, SYMBOL_NAME (sym) + 1))
+ if (SYMBOL_NAME (msymbol)[0] == SYMBOL_NAME (sym)[0] &&
+ STREQ(SYMBOL_NAME (msymbol) + 1, SYMBOL_NAME (sym) + 1))
{
/* Splice this symbol out of the hash chain and
assign the value we have to it. */
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
{
- fix_common_block (sym, msymbol -> address);
+ fix_common_block (sym, SYMBOL_VALUE_ADDRESS (msymbol));
}
else
{
- SYMBOL_VALUE_ADDRESS (sym) = msymbol -> address;
+ SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msymbol);
}
if (prev)