mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-01-24 02:14:28 +00:00
Improve G++ debugging support.
This commit is contained in:
parent
7d7ecbddb0
commit
f1d77e9053
@ -1,3 +1,36 @@
|
||||
Wed Nov 27 01:23:41 1991 John Gilmore (gnu at cygnus.com)
|
||||
|
||||
Fix bugs in C++ debugging.
|
||||
|
||||
* symtab.h: target_type is not used in record types.
|
||||
Eliminate TYPE_MAIN_VARIANT and TYPE_NEXT_VARIANT. Eliminate
|
||||
lookup_method_type.
|
||||
|
||||
* symtab.c (lookup_member_type): Don't chain them up, just
|
||||
allocate one in symbol_obstack when we need one.
|
||||
(allocate_stub_method): Build stub in symbol_obstack.
|
||||
(check_stub_method): Move here from values.c. Don't deallocate
|
||||
stub; overwrite it.
|
||||
(lookup_method_type): Gone now.
|
||||
|
||||
* buildsym.c: Handle g++ v1 stabs a little bit better.
|
||||
Change some C++ parsing error()s to complain()ts.
|
||||
* buildsym.c, findvar.c, printcmd.c, symtab.c: Make unions and
|
||||
structs have the same representation and work the same as far as
|
||||
C++ is concerned.
|
||||
* buildsym.c, symtab.c, values.c: Remove all references to
|
||||
TYPE_MAIN_VARIANT and TYPE_NEXT_VARIANT.
|
||||
|
||||
* valops.c: Improve comments and indentation. Only call
|
||||
check_stub_method when the stub flag is on.
|
||||
* valprint.c: Fix or mark minor bugs and unportabilities.
|
||||
|
||||
* coffread.c (anonymous unions): Allocate a cplus structure.
|
||||
|
||||
* mipsread.c: Eliminate "template" types. Build new, real
|
||||
types whenever we need them. Allocate cplus structures as needed.
|
||||
Bulletproof the type parsing a bit more. Mark storage leaks.
|
||||
|
||||
Fri Nov 22 16:39:57 1991 John Gilmore (gnu at cygnus.com)
|
||||
|
||||
* inflow.c (terminal_inferior): Check the results of ioctl's, and
|
||||
|
@ -93,8 +93,17 @@ You seem to have compiled your program with \
|
||||
Therefore GDB will not know about your class variables", 0, 0};
|
||||
#endif
|
||||
|
||||
struct complaint invalid_cpp_abbrev_complaint =
|
||||
{"invalid C++ abbreviation `%s'", 0, 0};
|
||||
|
||||
struct complaint invalid_cpp_type_complaint =
|
||||
{"C++ abbreviated type name unknown at symtab pos %d", 0, 0};
|
||||
|
||||
struct complaint member_fn_complaint =
|
||||
{"member function type missing, got '%c'", 0, 0};
|
||||
|
||||
struct complaint const_vol_complaint =
|
||||
{"const/volatile indicator missing (ok if using g++ v1.x), got '%c'", 0, 0};
|
||||
{"const/volatile indicator missing, got '%c'", 0, 0};
|
||||
|
||||
struct complaint error_type_complaint =
|
||||
{"debug info mismatch between compiler and debugger", 0, 0};
|
||||
@ -1635,7 +1644,7 @@ read_type (pp)
|
||||
type = dbx_alloc_type (typenums);
|
||||
TYPE_CODE (type) = code;
|
||||
TYPE_NAME (type) = type_name;
|
||||
if (code == TYPE_CODE_STRUCT)
|
||||
if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
|
||||
{
|
||||
TYPE_CPLUS_SPECIFIC (type)
|
||||
= (struct cplus_struct_type *) obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type));
|
||||
@ -1857,9 +1866,6 @@ read_struct_type (pp, type)
|
||||
register struct next_fnfieldlist *mainlist = 0;
|
||||
int nfn_fields = 0;
|
||||
|
||||
if (TYPE_MAIN_VARIANT (type) == 0)
|
||||
TYPE_MAIN_VARIANT (type) = type;
|
||||
|
||||
TYPE_CODE (type) = TYPE_CODE_STRUCT;
|
||||
TYPE_CPLUS_SPECIFIC (type)
|
||||
= (struct cplus_struct_type *) obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type));
|
||||
@ -1996,20 +2002,22 @@ read_struct_type (pp, type)
|
||||
prefix = vb_name;
|
||||
break;
|
||||
default:
|
||||
error ("invalid abbreviation at symtab pos %d.", symnum);
|
||||
complain (&invalid_cpp_abbrev_complaint, *pp);
|
||||
prefix = "INVALID_C++_ABBREV";
|
||||
break;
|
||||
}
|
||||
*pp = p + 1;
|
||||
context = read_type (pp);
|
||||
name = type_name_no_tag (context);
|
||||
if (name == 0)
|
||||
{
|
||||
error ("type name unknown at symtab pos %d.", symnum);
|
||||
complain (&invalid_cpp_type_complaint, symnum);
|
||||
TYPE_NAME (context) = name;
|
||||
}
|
||||
list->field.name = obconcat (prefix, name, "");
|
||||
p = ++(*pp);
|
||||
if (p[-1] != ':')
|
||||
error ("invalid abbreviation at symtab pos %d.", symnum);
|
||||
complain (&invalid_cpp_abbrev_complaint, *pp);
|
||||
list->field.type = read_type (pp);
|
||||
(*pp)++; /* Skip the comma. */
|
||||
list->field.bitpos = read_number (pp, ';');
|
||||
@ -2020,7 +2028,7 @@ read_struct_type (pp, type)
|
||||
else if (*p == '_')
|
||||
break;
|
||||
else
|
||||
error ("invalid abbreviation at symtab pos %d.", symnum);
|
||||
complain (&invalid_cpp_abbrev_complaint, *pp);
|
||||
|
||||
nfields++;
|
||||
continue;
|
||||
@ -2192,14 +2200,17 @@ read_struct_type (pp, type)
|
||||
|
||||
/* read in the name. */
|
||||
while (*p != ':') p++;
|
||||
#if 0
|
||||
if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == CPLUS_MARKER)
|
||||
{
|
||||
/* 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! */
|
||||
/* This lets the user type "break operator+".
|
||||
We could just put in "+" as the name, but that wouldn't
|
||||
work for "*". */
|
||||
/* I don't understand what this is trying to do.
|
||||
It seems completely bogus. -Per Bothner. */
|
||||
static char opname[32] = {'o', 'p', CPLUS_MARKER};
|
||||
char *o = opname + 3;
|
||||
|
||||
@ -2214,7 +2225,6 @@ read_struct_type (pp, type)
|
||||
*pp = p + 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
main_fn_name = savestring (*pp, p - *pp);
|
||||
/* Skip past '::'. */
|
||||
*pp = p + 2;
|
||||
@ -2272,10 +2282,13 @@ read_struct_type (pp, type)
|
||||
new_sublist->fn_field.is_volatile = 1;
|
||||
(*pp)++;
|
||||
break;
|
||||
case '*': /* File compiled with g++ version 1 -- no info */
|
||||
case '?':
|
||||
case '.':
|
||||
break;
|
||||
default:
|
||||
/* This probably just means we're processing a file compiled
|
||||
with g++ version 1. */
|
||||
complain(&const_vol_complaint, **pp);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (*(*pp)++)
|
||||
@ -2320,8 +2333,13 @@ read_struct_type (pp, type)
|
||||
/* static member function. */
|
||||
new_sublist->fn_field.voffset = VOFFSET_STATIC;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* **pp == '.'. */
|
||||
/* error */
|
||||
complain (&member_fn_complaint, (*pp)[-1]);
|
||||
/* Fall through into normal member function. */
|
||||
|
||||
case '.':
|
||||
/* normal member function. */
|
||||
new_sublist->fn_field.voffset = 0;
|
||||
new_sublist->fn_field.fcontext = 0;
|
||||
|
@ -1816,6 +1816,10 @@ decode_base_type (cs, c_type, aux)
|
||||
/* anonymous union type */
|
||||
type = coff_alloc_type (cs->c_symnum);
|
||||
TYPE_NAME (type) = concat ("union ", "<opaque>", NULL);
|
||||
TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
|
||||
obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type));
|
||||
bzero (TYPE_CPLUS_SPECIFIC (type), sizeof (struct cplus_struct_type));
|
||||
TYPE_LENGTH (type) = 0;
|
||||
TYPE_LENGTH (type) = 0;
|
||||
TYPE_FIELDS (type) = 0;
|
||||
TYPE_NFIELDS (type) = 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Read a symbol table in MIPS' format (Third-Eye).
|
||||
Copyright (C) 1986, 1987, 1989-1991 Free Software Foundation, Inc.
|
||||
Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU
|
||||
Copyright 1986, 1987, 1989, 1990, 1991 Free Software Foundation, Inc.
|
||||
Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
@ -161,15 +161,6 @@ struct type *builtin_type_fixed_dec;
|
||||
struct type *builtin_type_float_dec;
|
||||
struct type *builtin_type_string;
|
||||
|
||||
/* Template types */
|
||||
|
||||
static struct type *builtin_type_ptr;
|
||||
static struct type *builtin_type_struct;
|
||||
static struct type *builtin_type_union;
|
||||
static struct type *builtin_type_enum;
|
||||
static struct type *builtin_type_range;
|
||||
static struct type *builtin_type_set;
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
static struct symbol *new_symbol();
|
||||
@ -243,9 +234,6 @@ mipscoff_symfile_read(sf, addr, mainline)
|
||||
int symtab_offset;
|
||||
int stringtab_offset;
|
||||
|
||||
/* Initialize a variable that we couldn't do at _initialize_ time. */
|
||||
builtin_type_ptr = lookup_pointer_type (builtin_type_void);
|
||||
|
||||
/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
|
||||
desc = fileno ((FILE *)(abfd->iostream)); /* Raw file descriptor */
|
||||
/* End of warning */
|
||||
@ -1066,7 +1054,7 @@ static struct type *parse_type(ax, sh, bs)
|
||||
|
||||
TIR *t;
|
||||
struct type *tp = 0, *tp1;
|
||||
char *fmt = "%s";
|
||||
char *fmt;
|
||||
|
||||
/* Procedures start off by one */
|
||||
if (sh->st == stProc || sh->st == stStaticProc)
|
||||
@ -1079,38 +1067,43 @@ static struct type *parse_type(ax, sh, bs)
|
||||
|
||||
/* Use aux as a type information record, map its basic type */
|
||||
t = &ax->ti;
|
||||
if (t->bt > 26 || t->bt == btPicture) {
|
||||
if (t->bt > (sizeof (map_bt)/sizeof (*map_bt))) {
|
||||
complain (&basic_type_complaint, t->bt);
|
||||
return builtin_type_int;
|
||||
}
|
||||
if (map_bt[t->bt])
|
||||
tp = *map_bt[t->bt];
|
||||
fmt = "%s";
|
||||
else {
|
||||
/* Cannot use builtin types, use templates */
|
||||
tp = make_type(TYPE_CODE_VOID, 0, 0, 0);
|
||||
/* Cannot use builtin types -- build our own */
|
||||
switch (t->bt) {
|
||||
case btAdr:
|
||||
*tp = *builtin_type_ptr;
|
||||
tp = lookup_pointer_type (builtin_type_void);
|
||||
fmt = "%s";
|
||||
break;
|
||||
case btStruct:
|
||||
*tp = *builtin_type_struct;
|
||||
tp = make_struct_type(TYPE_CODE_STRUCT, 0, 0, 0);
|
||||
fmt = "struct %s";
|
||||
break;
|
||||
case btUnion:
|
||||
*tp = *builtin_type_union;
|
||||
tp = make_struct_type(TYPE_CODE_UNION, 0, 0, 0);
|
||||
fmt = "union %s";
|
||||
break;
|
||||
case btEnum:
|
||||
*tp = *builtin_type_enum;
|
||||
tp = make_type(TYPE_CODE_ENUM, 0, 0, 0);
|
||||
fmt = "enum %s";
|
||||
break;
|
||||
case btRange:
|
||||
*tp = *builtin_type_range;
|
||||
tp = make_type(TYPE_CODE_RANGE, 0, 0, 0);
|
||||
fmt = "%s";
|
||||
break;
|
||||
case btSet:
|
||||
*tp = *builtin_type_set;
|
||||
tp = make_type(TYPE_CODE_SET, 0, 0, 0);
|
||||
fmt = "set %s";
|
||||
break;
|
||||
default:
|
||||
complain (&basic_type_complaint, t->bt);
|
||||
return builtin_type_int;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2548,6 +2541,7 @@ make_type(code, length, uns, name)
|
||||
{
|
||||
register struct type *type;
|
||||
|
||||
/* FIXME, I don't think this ever gets freed. */
|
||||
type = (struct type *) xzalloc(sizeof(struct type));
|
||||
TYPE_CODE(type) = code;
|
||||
TYPE_LENGTH(type) = length;
|
||||
@ -2558,6 +2552,25 @@ make_type(code, length, uns, name)
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Create and initialize a new struct or union type, a la make_type. */
|
||||
|
||||
static
|
||||
struct type *
|
||||
make_struct_type(code, length, uns, name)
|
||||
enum type_code code;
|
||||
int length, uns;
|
||||
char *name;
|
||||
{
|
||||
register struct type *type;
|
||||
|
||||
type = make_type (code, length, uns, name);
|
||||
|
||||
/* FIXME, I don't think this ever gets freed. */
|
||||
TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
|
||||
xzalloc (sizeof (struct cplus_struct_type));
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Allocate a new field named NAME to the type TYPE */
|
||||
|
||||
static
|
||||
@ -2795,15 +2808,4 @@ _initialize_mipsread ()
|
||||
0, "fixed_decimal");
|
||||
builtin_type_float_dec = make_type(TYPE_CODE_FLT, sizeof(double),
|
||||
0, "floating_decimal");
|
||||
|
||||
/* Templates types */
|
||||
builtin_type_struct = make_type(TYPE_CODE_STRUCT, 0, 0, 0);
|
||||
builtin_type_union = make_type(TYPE_CODE_UNION, 0, 0, 0);
|
||||
builtin_type_enum = make_type(TYPE_CODE_ENUM, 0, 0, 0);
|
||||
builtin_type_range = make_type(TYPE_CODE_RANGE, 0, 0, 0);
|
||||
builtin_type_set = make_type(TYPE_CODE_SET, 0, 0, 0);
|
||||
|
||||
/* We can't do this now because builtin_type_void may not
|
||||
be set yet. Do it at symbol reading time. */
|
||||
/* builtin_type_ptr = lookup_pointer_type (builtin_type_void); */
|
||||
}
|
||||
|
@ -318,7 +318,8 @@ vx_call_function (function, nargs, args)
|
||||
to the structure, not the structure itself. */
|
||||
if (REG_STRUCT_HAS_ADDR (using_gcc))
|
||||
for (i = nargs - 1; i >= 0; i--)
|
||||
if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
|
||||
if ( TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_UNION)
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
#if !(1 INNER_THAN 2)
|
||||
|
292
gdb/symtab.c
292
gdb/symtab.c
@ -393,7 +393,7 @@ lookup_template_type (name, type, block)
|
||||
strcpy(nam, name);
|
||||
strcat(nam, "<");
|
||||
strcat(nam, type->name);
|
||||
strcat(nam, " >"); /* extra space still introduced in gcc? */
|
||||
strcat(nam, " >"); /* FIXME, extra space still introduced in gcc? */
|
||||
|
||||
sym = lookup_symbol (nam, block, VAR_NAMESPACE, 0, (struct symtab **)NULL);
|
||||
|
||||
@ -416,7 +416,7 @@ lookup_struct_elt_type (type, name, noerr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
if ( TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION)
|
||||
{
|
||||
target_terminal_ours ();
|
||||
@ -524,212 +524,118 @@ struct type *
|
||||
lookup_member_type (type, domain)
|
||||
struct type *type, *domain;
|
||||
{
|
||||
register struct type *mtype = TYPE_MAIN_VARIANT (type);
|
||||
struct type *main_type;
|
||||
|
||||
main_type = mtype;
|
||||
while (mtype)
|
||||
{
|
||||
if (TYPE_DOMAIN_TYPE (mtype) == domain)
|
||||
return mtype;
|
||||
mtype = TYPE_NEXT_VARIANT (mtype);
|
||||
}
|
||||
|
||||
/* This is the first time anyone wanted this member type. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
mtype = (struct type *) xmalloc (sizeof (struct type));
|
||||
else
|
||||
mtype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
|
||||
bzero (mtype, sizeof (struct type));
|
||||
if (main_type == 0)
|
||||
main_type = mtype;
|
||||
else
|
||||
{
|
||||
TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
|
||||
TYPE_NEXT_VARIANT (main_type) = mtype;
|
||||
}
|
||||
TYPE_MAIN_VARIANT (mtype) = main_type;
|
||||
TYPE_TARGET_TYPE (mtype) = type;
|
||||
TYPE_DOMAIN_TYPE (mtype) = domain;
|
||||
/* New type is permanent if type pointed to is permanent. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
|
||||
|
||||
/* In practice, this is never used. */
|
||||
TYPE_LENGTH (mtype) = 1;
|
||||
TYPE_CODE (mtype) = TYPE_CODE_MEMBER;
|
||||
|
||||
#if 0
|
||||
/* Now splice in the new member pointer type. */
|
||||
if (main_type)
|
||||
{
|
||||
/* This type was not "smashed". */
|
||||
TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
|
||||
TYPE_CHAIN (main_type) = mtype;
|
||||
}
|
||||
#endif
|
||||
register struct type *mtype;
|
||||
|
||||
mtype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
smash_to_member_type (mtype, domain, type);
|
||||
return mtype;
|
||||
}
|
||||
|
||||
/* Allocate a stub method whose return type is
|
||||
TYPE. We will fill in arguments later. This always
|
||||
returns a fresh type. If we unify this type with
|
||||
an existing type later, the storage allocated
|
||||
here can be freed. */
|
||||
/* Allocate a stub method whose return type is TYPE.
|
||||
This apparently happens for speed of symbol reading, since parsing
|
||||
out the arguments to the method is cpu-intensive, the way we are doing
|
||||
it. So, we will fill in arguments later.
|
||||
This always returns a fresh type. */
|
||||
|
||||
struct type *
|
||||
allocate_stub_method (type)
|
||||
struct type *type;
|
||||
{
|
||||
struct type *mtype = (struct type *)xmalloc (sizeof (struct type));
|
||||
struct type *mtype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
bzero (mtype, sizeof (struct type));
|
||||
TYPE_MAIN_VARIANT (mtype) = mtype;
|
||||
TYPE_TARGET_TYPE (mtype) = type;
|
||||
/* _DOMAIN_TYPE (mtype) = unknown yet */
|
||||
/* _ARG_TYPES (mtype) = unknown yet */
|
||||
TYPE_FLAGS (mtype) = TYPE_FLAG_STUB;
|
||||
TYPE_CODE (mtype) = TYPE_CODE_METHOD;
|
||||
TYPE_LENGTH (mtype) = 1;
|
||||
return mtype;
|
||||
}
|
||||
|
||||
/* Lookup a method type belonging to class DOMAIN, returning type TYPE,
|
||||
and taking a list of arguments ARGS.
|
||||
If one is not found, allocate a new one. */
|
||||
/* Ugly hack to convert method stubs into method types.
|
||||
|
||||
struct type *
|
||||
lookup_method_type (domain, type, args)
|
||||
struct type *domain, *type, **args;
|
||||
{
|
||||
register struct type *mtype = TYPE_MAIN_VARIANT (type);
|
||||
struct type *main_type;
|
||||
|
||||
main_type = mtype;
|
||||
while (mtype)
|
||||
{
|
||||
if (TYPE_DOMAIN_TYPE (mtype) == domain)
|
||||
{
|
||||
struct type **t1 = args;
|
||||
struct type **t2 = TYPE_ARG_TYPES (mtype);
|
||||
if (t2)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; t1[i] != 0 && t1[i]->code != TYPE_CODE_VOID; i++)
|
||||
if (t1[i] != t2[i])
|
||||
break;
|
||||
if (t1[i] == t2[i])
|
||||
return mtype;
|
||||
}
|
||||
}
|
||||
mtype = TYPE_NEXT_VARIANT (mtype);
|
||||
}
|
||||
|
||||
/* This is the first time anyone wanted this member type. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
mtype = (struct type *) xmalloc (sizeof (struct type));
|
||||
else
|
||||
mtype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
|
||||
bzero (mtype, sizeof (struct type));
|
||||
if (main_type == 0)
|
||||
main_type = mtype;
|
||||
else
|
||||
{
|
||||
TYPE_NEXT_VARIANT (mtype) = TYPE_NEXT_VARIANT (main_type);
|
||||
TYPE_NEXT_VARIANT (main_type) = mtype;
|
||||
}
|
||||
TYPE_MAIN_VARIANT (mtype) = main_type;
|
||||
TYPE_TARGET_TYPE (mtype) = type;
|
||||
TYPE_DOMAIN_TYPE (mtype) = domain;
|
||||
TYPE_ARG_TYPES (mtype) = args;
|
||||
/* New type is permanent if type pointed to is permanent. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
TYPE_FLAGS (mtype) |= TYPE_FLAG_PERM;
|
||||
|
||||
/* In practice, this is never used. */
|
||||
TYPE_LENGTH (mtype) = 1;
|
||||
TYPE_CODE (mtype) = TYPE_CODE_METHOD;
|
||||
|
||||
#if 0
|
||||
/* Now splice in the new member pointer type. */
|
||||
if (main_type)
|
||||
{
|
||||
/* This type was not "smashed". */
|
||||
TYPE_CHAIN (mtype) = TYPE_CHAIN (main_type);
|
||||
TYPE_CHAIN (main_type) = mtype;
|
||||
}
|
||||
#endif
|
||||
|
||||
return mtype;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Given a type TYPE, return a type which has offset OFFSET,
|
||||
via_virtual VIA_VIRTUAL, and via_public VIA_PUBLIC.
|
||||
May need to construct such a type if none exists. */
|
||||
struct type *
|
||||
lookup_basetype_type (type, offset, via_virtual, via_public)
|
||||
He ain't kiddin'. This demangles the name of the method into a string
|
||||
including argument types, parses out each argument type, generates
|
||||
a string casting a zero to that type, evaluates the string, and stuffs
|
||||
the resulting type into an argtype vector!!! Then it knows the type
|
||||
of the whole function (including argument types for overloading),
|
||||
which info used to be in the stab's but was removed to hack back
|
||||
the space required for them. */
|
||||
void
|
||||
check_stub_method (type, i, j)
|
||||
struct type *type;
|
||||
int offset;
|
||||
int via_virtual, via_public;
|
||||
int i, j;
|
||||
{
|
||||
register struct type *btype = TYPE_MAIN_VARIANT (type);
|
||||
struct type *main_type;
|
||||
extern char *gdb_mangle_name (), *strchr ();
|
||||
struct fn_field *f;
|
||||
char *mangled_name = gdb_mangle_name (type, i, j);
|
||||
char *demangled_name = cplus_demangle (mangled_name, 0);
|
||||
char *argtypetext, *p;
|
||||
int depth = 0, argcount = 1;
|
||||
struct type **argtypes;
|
||||
struct type *mtype;
|
||||
|
||||
if (offset != 0)
|
||||
/* Now, read in the parameters that define this type. */
|
||||
argtypetext = strchr (demangled_name, '(') + 1;
|
||||
p = argtypetext;
|
||||
while (*p)
|
||||
{
|
||||
printf ("Internal error: type offset non-zero in lookup_basetype_type");
|
||||
offset = 0;
|
||||
if (*p == '(')
|
||||
depth += 1;
|
||||
else if (*p == ')')
|
||||
depth -= 1;
|
||||
else if (*p == ',' && depth == 0)
|
||||
argcount += 1;
|
||||
|
||||
p += 1;
|
||||
}
|
||||
/* We need one more slot for the void [...] or NULL [end of arglist] */
|
||||
argtypes = (struct type **) obstack_alloc (symbol_obstack,
|
||||
(argcount+1) * sizeof (struct type *));
|
||||
p = argtypetext;
|
||||
argtypes[0] = lookup_pointer_type (type);
|
||||
argcount = 1;
|
||||
|
||||
if (*p != ')') /* () means no args, skip while */
|
||||
{
|
||||
depth = 0;
|
||||
while (*p)
|
||||
{
|
||||
if (depth <= 0 && (*p == ',' || *p == ')'))
|
||||
{
|
||||
argtypes[argcount] =
|
||||
parse_and_eval_type (argtypetext, p - argtypetext);
|
||||
argcount += 1;
|
||||
argtypetext = p + 1;
|
||||
}
|
||||
|
||||
if (*p == '(')
|
||||
depth += 1;
|
||||
else if (*p == ')')
|
||||
depth -= 1;
|
||||
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
|
||||
main_type = btype;
|
||||
while (btype)
|
||||
{
|
||||
if (/* TYPE_OFFSET (btype) == offset
|
||||
&& */ TYPE_VIA_PUBLIC (btype) == via_public
|
||||
&& TYPE_VIA_VIRTUAL (btype) == via_virtual)
|
||||
return btype;
|
||||
btype = TYPE_NEXT_VARIANT (btype);
|
||||
}
|
||||
|
||||
/* This is the first time anyone wanted this member type. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
btype = (struct type *) xmalloc (sizeof (struct type));
|
||||
if (p[-2] != '.') /* ... */
|
||||
argtypes[argcount] = builtin_type_void; /* Ellist terminator */
|
||||
else
|
||||
btype = (struct type *) obstack_alloc (symbol_obstack,
|
||||
sizeof (struct type));
|
||||
argtypes[argcount] = NULL; /* List terminator */
|
||||
|
||||
if (main_type == 0)
|
||||
{
|
||||
main_type = btype;
|
||||
bzero (btype, sizeof (struct type));
|
||||
TYPE_MAIN_VARIANT (btype) = main_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
bcopy (main_type, btype, sizeof (struct type));
|
||||
TYPE_NEXT_VARIANT (main_type) = btype;
|
||||
}
|
||||
/* TYPE_OFFSET (btype) = offset; */
|
||||
if (via_public)
|
||||
TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_PUBLIC;
|
||||
if (via_virtual)
|
||||
TYPE_FLAGS (btype) |= TYPE_FLAG_VIA_VIRTUAL;
|
||||
/* New type is permanent if type pointed to is permanent. */
|
||||
if (TYPE_FLAGS (type) & TYPE_FLAG_PERM)
|
||||
TYPE_FLAGS (btype) |= TYPE_FLAG_PERM;
|
||||
free (demangled_name);
|
||||
|
||||
/* In practice, this is never used. */
|
||||
TYPE_LENGTH (btype) = 1;
|
||||
TYPE_CODE (btype) = TYPE_CODE_STRUCT;
|
||||
TYPE_CPLUS_SPECIFIC (btype)
|
||||
= (struct cplus_struct_type *) obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type)));
|
||||
bzero (TYPE_CPLUS_SPECIFIC (btype), sizeof (struct cplus_struct_type));
|
||||
f = TYPE_FN_FIELDLIST1 (type, i);
|
||||
TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
|
||||
|
||||
return btype;
|
||||
/* Now update the old "stub" type into a real type. */
|
||||
mtype = TYPE_FN_FIELD_TYPE (f, j);
|
||||
TYPE_DOMAIN_TYPE (mtype) = type;
|
||||
TYPE_ARG_TYPES (mtype) = argtypes;
|
||||
TYPE_FLAGS (mtype) &= ~TYPE_FLAG_STUB;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Given a type TYPE, return a type of functions that return that type.
|
||||
May need to construct such a type if this is the first use. */
|
||||
@ -813,7 +719,11 @@ create_array_type (element_type, number)
|
||||
}
|
||||
|
||||
|
||||
/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. */
|
||||
/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE.
|
||||
A MEMBER is a wierd thing -- it amounts to a typed offset into
|
||||
a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't
|
||||
include the offset (that's the value of the MEMBER itself), but does
|
||||
include the structure type into which it points (for some reason). */
|
||||
|
||||
void
|
||||
smash_to_member_type (type, domain, to_type)
|
||||
@ -822,15 +732,12 @@ smash_to_member_type (type, domain, to_type)
|
||||
bzero (type, sizeof (struct type));
|
||||
TYPE_TARGET_TYPE (type) = to_type;
|
||||
TYPE_DOMAIN_TYPE (type) = domain;
|
||||
|
||||
/* In practice, this is never needed. */
|
||||
TYPE_LENGTH (type) = 1;
|
||||
TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
|
||||
TYPE_CODE (type) = TYPE_CODE_MEMBER;
|
||||
|
||||
TYPE_MAIN_VARIANT (type) = lookup_member_type (domain, to_type);
|
||||
}
|
||||
|
||||
/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE. */
|
||||
/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE.
|
||||
METHOD just means `function that gets an extra "this" argument'. */
|
||||
|
||||
void
|
||||
smash_to_method_type (type, domain, to_type, args)
|
||||
@ -840,12 +747,8 @@ smash_to_method_type (type, domain, to_type, args)
|
||||
TYPE_TARGET_TYPE (type) = to_type;
|
||||
TYPE_DOMAIN_TYPE (type) = domain;
|
||||
TYPE_ARG_TYPES (type) = args;
|
||||
|
||||
/* In practice, this is never needed. */
|
||||
TYPE_LENGTH (type) = 1;
|
||||
TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
|
||||
TYPE_CODE (type) = TYPE_CODE_METHOD;
|
||||
|
||||
TYPE_MAIN_VARIANT (type) = lookup_method_type (domain, to_type, args);
|
||||
}
|
||||
|
||||
/* Find which partial symtab on the partial_symtab_list contains
|
||||
@ -1988,7 +1891,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line)
|
||||
(struct symtab **)NULL);
|
||||
|
||||
if (sym_class &&
|
||||
(TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_STRUCT
|
||||
( TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (SYMBOL_TYPE (sym_class)) == TYPE_CODE_UNION))
|
||||
{
|
||||
/* Arg token is not digits => try it as a function name
|
||||
@ -2772,11 +2675,10 @@ init_type (code, length, uns, name)
|
||||
TYPE_NAME (type) = name;
|
||||
|
||||
/* C++ fancies. */
|
||||
if (code == TYPE_CODE_STRUCT)
|
||||
if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
|
||||
{
|
||||
TYPE_CPLUS_SPECIFIC (type)
|
||||
= (struct cplus_struct_type *) xmalloc (sizeof (struct cplus_struct_type));
|
||||
TYPE_MAIN_VARIANT (type) = type;
|
||||
TYPE_NFN_FIELDS (type) = 0;
|
||||
TYPE_N_BASECLASSES (type) = 0;
|
||||
}
|
||||
|
26
gdb/symtab.h
26
gdb/symtab.h
@ -131,10 +131,9 @@ struct type
|
||||
For an array type, describes the type of the elements.
|
||||
For a function or method type, describes the type of the value.
|
||||
For a range type, describes the type of the full range.
|
||||
For a record type, it's the "main variant" of the record type,
|
||||
used for computing pointers to members.
|
||||
Unused otherwise. */
|
||||
struct type *target_type;
|
||||
|
||||
/* Type that is a pointer to this type.
|
||||
Zero if no such pointer-to type is known yet.
|
||||
The debugger may add the address of such a type
|
||||
@ -142,7 +141,6 @@ struct type
|
||||
struct type *pointer_type;
|
||||
/* C++: also need a reference type. */
|
||||
struct type *reference_type;
|
||||
|
||||
/* Type that is a function returning this type.
|
||||
Zero if no such function type is known here.
|
||||
The debugger may add the address of such a type
|
||||
@ -189,7 +187,7 @@ struct type
|
||||
the field number of that pointer in the structure.
|
||||
|
||||
For types that are pointer to member types, VPTR_BASETYPE
|
||||
ifs the type that this pointer is a member of.
|
||||
is the type that this pointer is a member of.
|
||||
|
||||
Unused otherwise. */
|
||||
struct type *vptr_basetype;
|
||||
@ -204,23 +202,10 @@ struct type
|
||||
} type_specific;
|
||||
};
|
||||
|
||||
/* C++ language-specific information for TYPE_CODE_STRUCT nodes. */
|
||||
/* C++ language-specific information for TYPE_CODE_STRUCT and TYPE_CODE_UNION
|
||||
nodes. */
|
||||
struct cplus_struct_type
|
||||
{
|
||||
/* Handling of pointers to members:
|
||||
TYPE_MAIN_VARIANT is used for pointer and pointer
|
||||
to member types. Normally it is the value of the address of its
|
||||
containing type. However, for pointers to members, we must be
|
||||
able to allocate pointer to member types and look them up
|
||||
from some place of reference.
|
||||
NEXT_VARIANT is the next element in the chain.
|
||||
|
||||
A long time ago (Jul 88; GDB 2.5) Tiemann said that
|
||||
MAIN_VARIANT/NEXT_VARIANT may no longer be necessary and that he
|
||||
might eliminate it. I don't know whether this is still true (or
|
||||
ever was). */
|
||||
struct type *next_variant;
|
||||
|
||||
B_TYPE *virtual_field_bits; /* if base class is virtual */
|
||||
B_TYPE *private_field_bits;
|
||||
B_TYPE *protected_field_bits;
|
||||
@ -676,8 +661,6 @@ int current_source_line;
|
||||
#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
|
||||
#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
|
||||
#define TYPE_FUNCTION_TYPE(thistype) (thistype)->function_type
|
||||
#define TYPE_MAIN_VARIANT(thistype) (thistype)->target_type
|
||||
#define TYPE_NEXT_VARIANT(thistype) (TYPE_CPLUS_SPECIFIC (thistype))->next_variant
|
||||
#define TYPE_LENGTH(thistype) (thistype)->length
|
||||
#define TYPE_FLAGS(thistype) (thistype)->flags
|
||||
#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
|
||||
@ -812,7 +795,6 @@ extern int contained_in();
|
||||
extern struct type *lookup_template_type ();
|
||||
extern struct type *lookup_reference_type ();
|
||||
extern struct type *lookup_member_type ();
|
||||
extern struct type *lookup_method_type ();
|
||||
extern void smash_to_method_type ();
|
||||
void smash_to_member_type (
|
||||
#ifdef __STDC__
|
||||
|
89
gdb/values.c
89
gdb/values.c
@ -1147,7 +1147,7 @@ value_static_field (type, fieldname, fieldno)
|
||||
}
|
||||
|
||||
/* Compute the address of the baseclass which is
|
||||
the INDEXth baseclass of TYPE. The TYPE base
|
||||
the INDEXth baseclass of class TYPE. The TYPE base
|
||||
of the object is at VALADDR.
|
||||
|
||||
If ERRP is non-NULL, set *ERRP to be the errno code of any error,
|
||||
@ -1175,9 +1175,6 @@ baseclass_addr (type, index, valaddr, valuep, errp)
|
||||
register int n_baseclasses = TYPE_N_BASECLASSES (type);
|
||||
char *vbase_name, *type_name = type_name_no_tag (basetype);
|
||||
|
||||
if (TYPE_MAIN_VARIANT (basetype))
|
||||
basetype = TYPE_MAIN_VARIANT (basetype);
|
||||
|
||||
vbase_name = (char *)alloca (strlen (type_name) + 8);
|
||||
sprintf (vbase_name, "_vb$%s", type_name);
|
||||
/* First look for the virtual baseclass pointer
|
||||
@ -1238,84 +1235,6 @@ baseclass_addr (type, index, valaddr, valuep, errp)
|
||||
*valuep = 0;
|
||||
return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
|
||||
}
|
||||
|
||||
/* Ugly hack to convert method stubs into method types.
|
||||
|
||||
He ain't kiddin'. This demangles the name of the method into a string
|
||||
including argument types, parses out each argument type, generates
|
||||
a string casting a zero to that type, evaluates the string, and stuffs
|
||||
the resulting type into an argtype vector!!! Then it knows the type
|
||||
of the whole function (including argument types for overloading),
|
||||
which info used to be in the stab's but was removed to hack back
|
||||
the space required for them. */
|
||||
void
|
||||
check_stub_method (type, i, j)
|
||||
struct type *type;
|
||||
int i, j;
|
||||
{
|
||||
extern char *gdb_mangle_name (), *strchr ();
|
||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
|
||||
char *mangled_name = gdb_mangle_name (type, i, j);
|
||||
char *demangled_name = cplus_demangle (mangled_name, 0);
|
||||
char *argtypetext, *p;
|
||||
int depth = 0, argcount = 1;
|
||||
struct type **argtypes;
|
||||
|
||||
/* Now, read in the parameters that define this type. */
|
||||
argtypetext = strchr (demangled_name, '(') + 1;
|
||||
p = argtypetext;
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '(')
|
||||
depth += 1;
|
||||
else if (*p == ')')
|
||||
depth -= 1;
|
||||
else if (*p == ',' && depth == 0)
|
||||
argcount += 1;
|
||||
|
||||
p += 1;
|
||||
}
|
||||
/* We need one more slot for the void [...] or NULL [end of arglist] */
|
||||
argtypes = (struct type **)xmalloc ((argcount+1) * sizeof (struct type *));
|
||||
p = argtypetext;
|
||||
argtypes[0] = lookup_pointer_type (type);
|
||||
argcount = 1;
|
||||
|
||||
if (*p != ')') /* () means no args, skip while */
|
||||
{
|
||||
depth = 0;
|
||||
while (*p)
|
||||
{
|
||||
if (depth <= 0 && (*p == ',' || *p == ')'))
|
||||
{
|
||||
argtypes[argcount] =
|
||||
parse_and_eval_type (argtypetext, p - argtypetext);
|
||||
argcount += 1;
|
||||
argtypetext = p + 1;
|
||||
}
|
||||
|
||||
if (*p == '(')
|
||||
depth += 1;
|
||||
else if (*p == ')')
|
||||
depth -= 1;
|
||||
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (p[-2] != '.') /* ... */
|
||||
argtypes[argcount] = builtin_type_void; /* Ellist terminator */
|
||||
else
|
||||
argtypes[argcount] = NULL; /* List terminator */
|
||||
|
||||
free (demangled_name);
|
||||
|
||||
type = lookup_method_type (type, TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), argtypes);
|
||||
/* Free the stub type...it's no longer needed. */
|
||||
free (TYPE_FN_FIELD_TYPE (f, j));
|
||||
TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
|
||||
TYPE_FN_FIELD_TYPE (f, j) = type;
|
||||
}
|
||||
|
||||
long
|
||||
unpack_field_as_long (type, valaddr, fieldno)
|
||||
@ -1548,9 +1467,9 @@ set_return_value (val)
|
||||
if (code == TYPE_CODE_ERROR)
|
||||
error ("Function return type unknown.");
|
||||
|
||||
if (code == TYPE_CODE_STRUCT
|
||||
|| code == TYPE_CODE_UNION)
|
||||
error ("Specifying a struct or union return value is not supported.");
|
||||
if ( code == TYPE_CODE_STRUCT
|
||||
|| code == TYPE_CODE_UNION) /* FIXME, implement struct return. */
|
||||
error ("GDB does not support specifying a struct or union return value.");
|
||||
|
||||
/* FIXME, this is bogus. We don't know what the return conventions
|
||||
are, or how values should be promoted.... */
|
||||
|
Loading…
x
Reference in New Issue
Block a user