Add new support for parsing cfront stabs.

This commit is contained in:
Dawn Perchik 1996-04-24 19:34:45 +00:00
parent 50b802e0f5
commit 94f5a25f2e
4 changed files with 814 additions and 16 deletions

View File

@ -1,5 +1,5 @@
/* Read dbx symbol tables and convert to internal format, for GDB.
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
Free Software Foundation, Inc.
This file is part of GDB.
@ -65,6 +65,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "aout/aout64.h"
#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */
/* defined in stabsread.c; used for completing cfront stabs strings */
extern void resolve_cont PARAMS((struct objfile * objfile, struct symbol * sym, char * p));
/* We put a pointer to this structure in the read_symtab_private field
of the psymtab. */
@ -242,7 +245,7 @@ static void
init_bincl_list PARAMS ((int, struct objfile *));
static char *
dbx_next_symbol_text PARAMS ((void));
dbx_next_symbol_text PARAMS ((struct objfile *));
static void
fill_symbuf PARAMS ((bfd *));
@ -706,6 +709,7 @@ dbx_symfile_init (objfile)
DBX_STRINGTAB (objfile) =
(char *) obstack_alloc (&objfile -> psymbol_obstack,
DBX_STRINGTAB_SIZE (objfile));
OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile));
/* Now read in the string table in one big gulp. */
@ -742,6 +746,68 @@ static struct internal_nlist symbuf[4096];
static int symbuf_idx;
static int symbuf_end;
/* cont_elem is used for continuing information in cfront.
It saves information about which types need to be fixed up and
completed after all the stabs are read. */
struct cont_elem
{
/* sym and stabsstring for continuing information in cfront */
struct symbol * sym;
char * stabs;
/* state dependancies (statics that must be preserved) */
int sym_idx;
int sym_end;
int symnum;
/* other state dependancies include:
(assumption is that these will not change since process_now FIXME!!)
stringtab_global
n_stabs
objfile
symfile_bfd */
};
static struct cont_elem cont_list[100];
static int cont_count = 0;
void
process_later(sym,p)
struct symbol * sym;
char * p;
{
/* save state so we can process these stabs later */
cont_list[cont_count].sym_idx = symbuf_idx;
cont_list[cont_count].sym_end = symbuf_end;
cont_list[cont_count].symnum = symnum;
cont_list[cont_count].sym = sym;
cont_list[cont_count].stabs = p;
cont_count++;
}
void
process_now(objfile)
struct objfile * objfile;
{
int i;
/* save original state */
int save_symbuf_idx = symbuf_idx;
int save_symbuf_end = symbuf_end;
int save_symnum = symnum;
for (i=0; i<cont_count; i++)
{
/* set state as if we were parsing stabs strings
for this symbol */
symbuf_idx = cont_list[i].sym_idx; /* statics used by gdb */
symbuf_end = cont_list[i].sym_end;
symnum = cont_list[i].symnum;
resolve_cont(objfile,cont_list[i].sym,cont_list[i].stabs);
}
/* restore original state */
symbuf_idx = save_symbuf_idx;
symbuf_end = save_symbuf_end;
symnum = save_symnum;
cont_count=0; /* reset for next run */
}
/* Name of last function encountered. Used in Solaris to approximate
object file boundaries. */
static char *last_function_name;
@ -825,12 +891,14 @@ fill_symbuf (sym_bfd)
call this function to get the continuation. */
static char *
dbx_next_symbol_text ()
dbx_next_symbol_text (objfile)
struct objfile *objfile;
{
if (symbuf_idx == symbuf_end)
fill_symbuf (symfile_bfd);
symnum++;
SWAP_SYMBOL(&symbuf[symbuf_idx], symfile_bfd);
OBJSTAT (objfile, n_stabs++);
return symbuf[symbuf_idx++].n_strx + stringtab_global
+ file_string_table_offset;
}
@ -1066,6 +1134,7 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
int nsl;
int past_first_source_file = 0;
CORE_ADDR last_o_file_start = 0;
CORE_ADDR last_function_start = 0;
struct cleanup *back_to;
bfd *abfd;
@ -1128,6 +1197,7 @@ read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
if (bufp->n_type == (unsigned char)N_SLINE) continue;
SWAP_SYMBOL (bufp, abfd);
OBJSTAT (objfile, n_stabs++);
/* Ok. There is a lot of code duplicated in the rest of this
switch statement (for efficiency reasons). Since I don't
@ -1207,8 +1277,8 @@ start_psymtab (objfile, section_offsets,
char *filename;
CORE_ADDR textlow;
int ldsymoff;
struct partial_symbol *global_syms;
struct partial_symbol *static_syms;
struct partial_symbol **global_syms;
struct partial_symbol **static_syms;
{
struct partial_symtab *result =
start_psymtab_common(objfile, section_offsets,
@ -1561,6 +1631,7 @@ read_ofile_symtab (pst)
fill_symbuf (abfd);
bufp = &symbuf[symbuf_idx++];
SWAP_SYMBOL (bufp, abfd);
OBJSTAT (objfile, n_stabs++);
SET_NAMESTRING ();
@ -1616,6 +1687,7 @@ read_ofile_symtab (pst)
fill_symbuf(abfd);
bufp = &symbuf[symbuf_idx++];
SWAP_SYMBOL (bufp, abfd);
OBJSTAT (objfile, n_stabs++);
type = bufp->n_type;
@ -1669,8 +1741,17 @@ read_ofile_symtab (pst)
if (last_source_start_addr == 0)
last_source_start_addr = text_offset;
pst->symtab = end_symtab (text_offset + text_size, 0, 0, objfile,
SECT_OFF_TEXT);
/* In reordered executables last_source_start_addr may not be the
lower bound for this symtab, instead use text_offset which comes
from pst->textlow which is correct. */
if (last_source_start_addr > text_offset)
last_source_start_addr = text_offset;
pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT);
if (ARM_DEMANGLING) /* process incomplete C++ types now */
process_now(objfile);
end_stabs ();
}
@ -1745,6 +1826,21 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
{
case N_FUN:
case N_FNAME:
if (! strcmp (name, ""))
{
/* This N_FUN marks the end of a function. This closes off the
current block. */
within_function = 0;
new = pop_context ();
/* Make a block for the local symbols within. */
finish_block (new->name, &local_symbols, new->old_blocks,
function_start_offset, function_start_offset + valu,
objfile);
break;
}
/* Relocate for dynamic loading */
valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
goto define_a_symbol;
@ -1896,7 +1992,7 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
patch_subfile_names (current_subfile, name);
break; /* Ignore repeated SOs */
}
end_symtab (valu, 0, 0, objfile, SECT_OFF_TEXT);
end_symtab (valu, objfile, SECT_OFF_TEXT);
end_stabs ();
}
@ -2131,7 +2227,8 @@ process_one_symbol (type, desc, valu, name, section_offsets, objfile)
&& SYMBOL_NAME (m) [l] == '\0')
/* last_pc_address was in this function */
valu = SYMBOL_VALUE (m);
else if (m && STREQN (SYMBOL_NAME (m+1), name, l)
else if (m && SYMBOL_NAME (m+1)
&& STREQN (SYMBOL_NAME (m+1), name, l)
&& SYMBOL_NAME (m+1) [l] == '\0')
/* last_pc_address was in last function */
valu = SYMBOL_VALUE (m+1);
@ -2268,6 +2365,7 @@ coffstab_build_psymtabs (objfile, section_offsets, mainline,
error ("ridiculous string table size: %d bytes", stabstrsize);
DBX_STRINGTAB (objfile) = (char *)
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
OBJSTAT (objfile, sz_strtab += stabstrsize+1);
/* Now read in the string table in one big gulp. */
@ -2373,6 +2471,7 @@ elfstab_build_psymtabs (objfile, section_offsets, mainline,
error ("ridiculous string table size: %d bytes", stabstrsize);
DBX_STRINGTAB (objfile) = (char *)
obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
OBJSTAT (objfile, sz_strtab += stabstrsize+1);
/* Now read in the string table in one big gulp. */
@ -2460,6 +2559,7 @@ stabsect_build_psymtabs (objfile, section_offsets, mainline, stab_name,
error ("ridiculous string table size: %d bytes", DBX_STRINGTAB_SIZE (objfile));
DBX_STRINGTAB (objfile) = (char *)
obstack_alloc (&objfile->psymbol_obstack, DBX_STRINGTAB_SIZE (objfile) + 1);
OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile) + 1);
/* Now read in the string table in one big gulp. */

View File

@ -971,6 +971,199 @@ check_typedef (type)
return type;
}
/* New code added to support parsing of Cfront stabs strings */
#include <ctype.h>
#define INIT_EXTRA { pextras->len=0; pextras->str[0]='\0'; }
#define ADD_EXTRA(c) { pextras->str[pextras->len++]=c; }
struct extra { char str[128]; int len; }; /* maximum extention is 128! FIXME */
void
add_name(pextras,n)
struct extra * pextras;
char * n;
{
char lenstr[512]; /* FIXME! hardcoded :-( */
int nlen, lenstrlen;
if ((nlen = (n ? strlen(n) : 0))==0)
return;
sprintf(pextras->str+pextras->len,"%d%s",nlen,n);
pextras->len=strlen(pextras->str);
}
void
add_mangled_type(pextras,t)
struct extra * pextras;
struct type * t;
{
enum type_code tcode;
int tlen, tflags;
char * tname;
tcode = TYPE_CODE(t);
tlen = TYPE_LENGTH(t);
tflags = TYPE_FLAGS(t);
tname = TYPE_NAME(t);
/* args of "..." seem to get mangled as "e" */
switch (tcode)
{
case TYPE_CODE_INT:
if (tflags==1)
ADD_EXTRA('U');
switch (tlen)
{
case 1:
ADD_EXTRA('c');
break;
case 2:
ADD_EXTRA('s');
break;
case 4:
{
char* pname;
if ((pname=strrchr(tname,'l'),pname) && !strcmp(pname,"long"))
ADD_EXTRA('l')
else
ADD_EXTRA('i')
}
break;
default:
{
static struct complaint msg = {"Bad int type code length x%x\n",0,0};
complain (&msg, tlen);
}
}
break;
case TYPE_CODE_FLT:
switch (tlen)
{
case 4:
ADD_EXTRA('f');
break;
case 8:
ADD_EXTRA('d');
break;
case 16:
ADD_EXTRA('r');
break;
default:
{
static struct complaint msg = {"Bad float type code length x%x\n",0,0};
complain (&msg, tlen);
}
}
break;
case TYPE_CODE_REF:
ADD_EXTRA('R');
/* followed by what it's a ref to */
break;
case TYPE_CODE_PTR:
ADD_EXTRA('P');
/* followed by what it's a ptr to */
break;
case TYPE_CODE_TYPEDEF:
{
static struct complaint msg = {"Typedefs in overloaded functions not yet supported\n",0,0};
complain (&msg);
}
/* followed by type bytes & name */
break;
case TYPE_CODE_FUNC:
ADD_EXTRA('F');
/* followed by func's arg '_' & ret types */
break;
case TYPE_CODE_VOID:
ADD_EXTRA('v');
break;
case TYPE_CODE_METHOD:
ADD_EXTRA('M');
/* followed by name of class and func's arg '_' & ret types */
add_name(pextras,tname);
ADD_EXTRA('F'); /* then mangle function */
break;
case TYPE_CODE_STRUCT: /* C struct */
case TYPE_CODE_UNION: /* C union */
case TYPE_CODE_ENUM: /* Enumeration type */
/* followed by name of type */
add_name(pextras,tname);
break;
/* errors possible types/not supported */
case TYPE_CODE_CHAR:
case TYPE_CODE_ARRAY: /* Array type */
case TYPE_CODE_MEMBER: /* Member type */
case TYPE_CODE_BOOL:
case TYPE_CODE_COMPLEX: /* Complex float */
case TYPE_CODE_UNDEF:
case TYPE_CODE_SET: /* Pascal sets */
case TYPE_CODE_RANGE:
case TYPE_CODE_STRING:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_ERROR:
default:
{
static struct complaint msg = {"Unknown type code x%x\n",0,0};
complain (&msg, tcode);
}
}
if (t->target_type)
add_mangled_type(pextras,t->target_type);
}
char *
cfront_mangle_name(type, i, j)
struct type *type;
int i;
int j;
{
struct fn_field *f;
char *mangled_name = gdb_mangle_name (type, i, j);
f = TYPE_FN_FIELDLIST1 (type, i); /* moved from below */
/* kludge to support cfront methods - gdb expects to find "F" for
ARM_mangled names, so when we mangle, we have to add it here */
if (ARM_DEMANGLING)
{
int k;
char * arm_mangled_name;
struct fn_field *method = &f[j];
char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
char *newname = type_name_no_tag (type);
struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
int nargs = TYPE_NFIELDS(ftype); /* number of args */
struct extra extras, * pextras = &extras;
INIT_EXTRA
if (TYPE_FN_FIELD_STATIC_P (f, j)) /* j for sublist within this list */
ADD_EXTRA('S')
ADD_EXTRA('F')
/* add args here! */
if (nargs <= 1) /* no args besides this */
ADD_EXTRA('v')
else {
for (k=1; k<nargs; k++)
{
struct type * t;
t = TYPE_FIELD_TYPE(ftype,k);
add_mangled_type(pextras,t);
}
}
ADD_EXTRA('\0')
printf("add_mangled_type: %s\n",extras.str); /* FIXME */
arm_mangled_name = malloc(strlen(mangled_name)+extras.len);
sprintf(arm_mangled_name,"%s%s",mangled_name,extras.str);
free(mangled_name);
mangled_name = arm_mangled_name;
}
}
#undef ADD_EXTRA
/* End of new code added to support parsing of Cfront stabs strings */
/* Ugly hack to convert method stubs into method types.
He ain't kiddin'. This demangles the name of the method into a string
@ -1075,7 +1268,8 @@ check_stub_method (type, i, j)
free (demangled_name);
f = TYPE_FN_FIELDLIST1 (type, i);
f = TYPE_FN_FIELDLIST1 (type, i);
TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
/* Now update the old "stub" type into a real type. */

View File

@ -635,6 +635,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
case '8':
case '9':
case '-':
/* added to support cfront stabs strings */
case 'Z': /* for definition continuations */
case 'P': /* for prototypes */
continue;
case ':':

View File

@ -497,6 +497,489 @@ read_type_number (pp, typenums)
#define REG_STRUCT_HAS_ADDR(gcc_p,type) 0
#endif
#define VISIBILITY_PRIVATE '0' /* Stabs character for private field */
#define VISIBILITY_PROTECTED '1' /* Stabs character for protected fld */
#define VISIBILITY_PUBLIC '2' /* Stabs character for public field */
#define VISIBILITY_IGNORE '9' /* Optimized out or zero length */
#define CFRONT_VISIBILITY_PRIVATE '2' /* Stabs character for private field */
#define CFRONT_VISIBILITY_PUBLIC '1' /* Stabs character for public field */
/* This code added to support parsing of ARM/Cfront stabs strings */
/* get substring from string up to char c
advance string pointer past suibstring */
static char *
get_substring(p, c)
char ** p;
char c;
{
char * str;
str = *p;
*p = strchr(*p,c);
if (*p)
{
**p = 0;
(*p)++;
}
else
str = 0;
return str;
}
/* Physname gets strcat'd onto sname in order to recreate the mangled name
(see funtion gdb_mangle_name in gdbtypes.c). For cfront, make the physname
look like that of g++ - take out the initial mangling
eg: for sname="a" and fname="foo__1aFPFs_i" return "FPFs_i" */
static char *
get_cfront_method_physname(fname)
char * fname;
{
int len=0;
/* FIXME would like to make this generic for g++ too, but
that is already handled in read_member_funcctions */
char * p = fname;
/* search ahead to find the start of the mangled suffix */
if (*p == '_' && *(p+1)=='_') /* compiler generated; probably a ctor/dtor */
p+=2;
while (p && ((p+1) - fname) < strlen(fname) && *(p+1)!='_')
p = strchr(p,'_');
if (!(p && *p=='_' && *(p+1)=='_'))
error("Invalid mangled function name %s",fname);
p+=2; /* advance past '__' */
/* struct name length and name of type should come next; advance past it */
while (isdigit(*p))
{
len = len*10 + (*p - '0');
p++;
}
p+=len;
return p;
}
/* Read base classes within cfront class definition.
eg: class A : Bpri, public Bpub, virtual Bvir
A:T(0,27)=s20b__4Bpri:(0,3),0,32;OBpub:(0,25),32,8;a__1A:(0,3),64,32;PBvir:(0,28)=*(0,26),96,32;OBvir:(0,26),128,8;;
A:ZcA;2@Bpri 1@Bpub v2@Bvir;foopri__1AFv foopro__1AFv __ct__1AFv __ct__1AFRC1A foopub__1AFv ;;;
^^^^^^^^^^^^^^^^^^^^^
*/
static int
read_cfront_baseclasses(fip, pp, type, objfile)
struct field_info *fip;
struct objfile * objfile;
char ** pp;
struct type * type;
{
static struct complaint msg_noterm = {"\
Base classes not terminated while reading stabs string %s.\n",
0, 0};
static struct complaint msg_unknown = {"\
Unsupported token in stabs string %s.\n",
0, 0};
static struct complaint msg_notfound = {"\
Unable to find base type for %s.\n",
0, 0};
int bnum=0;
char * p;
int i;
struct nextfield *new;
if (**pp==';') /* no base classes; return */
{
*pp++;
return;
}
/* first count base classes so we can allocate space before parsing */
for (p = *pp; p && *p && *p!=';'; p++)
{
if (*p==' ') bnum++;
}
bnum++; /* add one more for last one */
/* now parse the base classes until we get to the start of the methods
(code extracted from read_baseclasses) */
TYPE_N_BASECLASSES(type) = bnum;
/* allocate space */
{
int num_bytes = B_BYTES (TYPE_N_BASECLASSES (type));
char *pointer;
pointer = (char *) TYPE_ALLOC (type, num_bytes);
TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
}
B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
{
new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
make_cleanup (free, new);
memset (new, 0, sizeof (struct nextfield));
new -> next = fip -> list;
fip -> list = new;
new -> field.bitsize = 0; /* this should be an unpacked field! */
STABS_CONTINUE (pp, objfile);
/* virtual? eg: v2@Bvir */
if (**pp=='v')
{
SET_TYPE_FIELD_VIRTUAL (type, i);
++(*pp);
}
/* access? eg: 2@Bvir */
/* Note: protected inheritance not supported in cfront */
switch (*(*pp)++)
{
case CFRONT_VISIBILITY_PRIVATE:
new -> visibility = VISIBILITY_PRIVATE;
break;
case CFRONT_VISIBILITY_PUBLIC:
new -> visibility = VISIBILITY_PUBLIC;
break;
default:
/* Bad visibility format. Complain and treat it as
public. */
{
static struct complaint msg = {
"Unknown visibility `%c' for baseclass", 0, 0};
complain (&msg, new -> visibility);
new -> visibility = VISIBILITY_PUBLIC;
}
}
/* "@" comes next - eg: @Bvir */
if (**pp!='@')
{
complain (&msg_unknown, *pp);
return;
}
++(*pp);
/* Set the bit offset of the portion of the object corresponding
to this baseclass. Always zero in the absence of
multiple inheritance. */
/* Unable to read bit position from stabs;
Assuming no multiple inheritance for now FIXME! */
/* We may have read this in the structure definition;
now we should fixup the members to be the actual base classes */
new -> field.bitpos = 0;
/* Get the base class name and type */
{
char * bname; /* base class name */
struct symbol * bsym; /* base class */
char * p1, * p2;
p1 = strchr(*pp,' ');
p2 = strchr(*pp,';');
if (p1<p2)
bname = get_substring(pp,' ');
else
bname = get_substring(pp,';');
if (!bname || !*bname)
{
complain (&msg_unknown, *pp);
return;
}
/* FIXME! attach base info to type */
bsym = lookup_symbol (bname, 0, STRUCT_NAMESPACE, 0, 0); /*demangled_name*/
if (bsym)
{
struct type * btype = SYMBOL_TYPE(bsym);
new -> field.type = btype;
new -> field.name = type_name_no_tag (new -> field.type);
}
else
{
complain (&msg_notfound, *pp);
return;
}
}
/* If more base classes to parse, loop again.
We ate the last ' ' or ';' in get_substring,
so on exit we will have skipped the trailing ';' */
/* if invalid, return 0; add code to detect - FIXME! */
}
return 1;
}
static int
read_cfront_member_functions(fip, pp, type, objfile)
struct field_info *fip;
char **pp;
struct type *type;
struct objfile *objfile;
{
/* This code extracted from read_member_functions
so as to do the similar thing for our funcs */
int nfn_fields = 0;
int length = 0;
/* Total number of member functions defined in this class. If the class
defines two `f' functions, and one `g' function, then this will have
the value 3. */
int total_length = 0;
int i;
struct next_fnfield
{
struct next_fnfield *next;
struct fn_field fn_field;
} *sublist;
struct type *look_ahead_type;
struct next_fnfieldlist *new_fnlist;
struct next_fnfield *new_sublist;
char *main_fn_name;
char * fname;
struct symbol * ref_func=0;
/* Process each list until we find something that is not a member function
or find the end of the functions. */
/* eg: p = "__ct__1AFv foo__1AFv ;;;" */
STABS_CONTINUE (pp, objfile); /* handle \\ */
while (**pp!=';' && (fname = get_substring(pp,' '),fname))
{
int is_static=0;
int sublist_count=0;
char * pname;
if (fname[0]=='*') /* static member */
{
is_static=1;
sublist_count++;
fname++;
}
ref_func = lookup_symbol (fname, 0, VAR_NAMESPACE, 0, 0); /*demangled_name*/
if (!ref_func)
{
static struct complaint msg = {"\
Unable to find function symbol for %s\n",
0, 0};
complain (&msg, fname);
continue;
}
sublist = NULL;
look_ahead_type = NULL;
length = 0;
new_fnlist = (struct next_fnfieldlist *)
xmalloc (sizeof (struct next_fnfieldlist));
make_cleanup (free, new_fnlist);
memset (new_fnlist, 0, sizeof (struct next_fnfieldlist));
/* The following is code to work around cfront generated stabs.
The stabs contains full mangled name for each field.
We try to demangle the name and extract the field name out of it. */
{
char *dem, *dem_p, *dem_args;
int dem_len;
dem = cplus_demangle (fname, DMGL_ANSI | DMGL_PARAMS);
if (dem != NULL)
{
dem_p = strrchr (dem, ':');
if (dem_p != 0 && *(dem_p-1)==':')
dem_p++;
/* get rid of args */
dem_args = strchr (dem_p, '(');
if (dem_args == NULL)
dem_len = strlen(dem_p);
else
dem_len = dem_args - dem_p;
main_fn_name =
obsavestring (dem_p, dem_len, &objfile -> type_obstack);
}
else
{
main_fn_name =
obsavestring (fname, strlen(fname), &objfile -> type_obstack);
}
} /* end of code for cfront work around */
new_fnlist -> fn_fieldlist.name = main_fn_name;
/*-------------------------------------------------*/
/* Set up the sublists
Sublists are stuff like args, static, visibility, etc.
so in ARM, we have to set that info some other way.
Multiple sublists happen if overloading
eg: foo::26=##1;:;2A.;
In g++, we'd loop here thru all the sublists... */
new_sublist =
(struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
make_cleanup (free, new_sublist);
memset (new_sublist, 0, sizeof (struct next_fnfield));
/* eat 1; from :;2A.; */
new_sublist -> fn_field.type = SYMBOL_TYPE(ref_func); /* normally takes a read_type */
/* make this type look like a method stub for gdb */
TYPE_FLAGS (new_sublist -> fn_field.type) |= TYPE_FLAG_STUB;
TYPE_CODE (new_sublist -> fn_field.type) = TYPE_CODE_METHOD;
/* If this is just a stub, then we don't have the real name here. */
if (TYPE_FLAGS (new_sublist -> fn_field.type) & TYPE_FLAG_STUB)
{
if (!TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type))
TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type) = type;
new_sublist -> fn_field.is_stub = 1;
}
/* physname used later in mangling; eg PFs_i,5 for foo__1aFPFs_i
physname gets strcat'd in order to recreate the onto mangled name */
pname = get_cfront_method_physname(fname);
new_sublist -> fn_field.physname = savestring (pname, strlen(pname));
/* Set this member function's visibility fields.
Unable to distinguish access from stabs definition!
Assuming public for now. FIXME!
(for private, set new_sublist->fn_field.is_private = 1,
for public, set new_sublist->fn_field.is_protected = 1) */
/* Unable to distinguish const/volatile from stabs definition!
Assuming normal for now. FIXME!
new_sublist -> fn_field.is_const = 0;
new_sublist -> fn_field.is_volatile = 0; /* volatile not implemented in cfront */
/* set virtual/static function info
How to get vtable offsets ?
Assuming normal for now FIXME!!
For vtables, figure out from whence this virtual function came.
It may belong to virtual function table of
one of its baseclasses.
set:
new_sublist -> fn_field.voffset = vtable offset,
new_sublist -> fn_field.fcontext = look_ahead_type;
where look_ahead_type is type of baseclass */
if (is_static)
new_sublist -> fn_field.voffset = VOFFSET_STATIC;
else /* normal member function. */
new_sublist -> fn_field.voffset = 0;
new_sublist -> fn_field.fcontext = 0;
/* prepare new sublist */
new_sublist -> next = sublist;
sublist = new_sublist;
length++;
/* In g++, we loop thu sublists - now we set from function */
new_fnlist -> fn_fieldlist.fn_fields = (struct fn_field *)
obstack_alloc (&objfile -> type_obstack,
sizeof (struct fn_field) * length);
memset (new_fnlist -> fn_fieldlist.fn_fields, 0,
sizeof (struct fn_field) * length);
for (i = length; (i--, sublist); sublist = sublist -> next)
{
new_fnlist -> fn_fieldlist.fn_fields[i] = sublist -> fn_field;
}
new_fnlist -> fn_fieldlist.length = length;
new_fnlist -> next = fip -> fnlist;
fip -> fnlist = new_fnlist;
nfn_fields++;
total_length += length;
STABS_CONTINUE (pp, objfile); /* handle \\ */
} /* end of loop */
if (nfn_fields)
{
/* type should already have space */
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * nfn_fields);
memset (TYPE_FN_FIELDLISTS (type), 0,
sizeof (struct fn_fieldlist) * nfn_fields);
TYPE_NFN_FIELDS (type) = nfn_fields;
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
/* end of scope for reading member func */
/* eg: ";;" */
/* skip trailing ';' and bump count of number of fields seen */
if (**pp == ';')
(*pp)++;
else
return 0;
return 1;
}
/* This routine fixes up partial cfront types that were created
while parsing the stabs. The main need for this function is
to add information such as methods to classes.
Examples of "p": "sA;;__ct__1AFv foo__1AFv ;;;" */
void
resolve_cont(objfile, sym, p)
struct objfile * objfile;
struct symbol * sym;
char * p;
{
struct symbol * ref_sym=0;
char * sname;
/* snarfed from read_struct_type */
struct field_info fi;
struct field_info * fip = &fi;
struct type *type;
struct cleanup *back_to;
/* need to make sure that fi isn't gunna conflict with struct
in case struct already had some fnfs */
fi.list = NULL;
fi.fnlist = NULL;
back_to = make_cleanup (null_cleanup, 0);
/* we only accept structs, classes and unions at the moment.
Other continuation types include t (typedef), r (long dbl), ...
We may want to add support for them as well;
right now they are handled by duplicating the symbol information
into the type information (see define_symbol) */
if (*p != 's' /* structs */
&& *p != 'c' /* class */
&& *p != 'u') /* union */
return; /* only handle C++ types */
p++;
/* get symbol typs name and validate
eg: p = "A;;__ct__1AFv foo__1AFv ;;;" */
sname = get_substring(&p,';');
if (!sname || strcmp(sname,SYMBOL_NAME(sym)))
error("Internal error: base symbol type name does not match\n");
/* find symbol's internal gdb reference */
ref_sym = lookup_symbol (SYMBOL_NAME(sym), 0, STRUCT_NAMESPACE, 0, 0); /*demangled_name*/
/* This is the real sym that we want;
sym was a temp hack to make debugger happy */
/* ref_sym should already have space */
type = SYMBOL_TYPE(ref_sym);
/* 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
field (baseclass specifier for the class holding the main vtable). */
if (!read_cfront_baseclasses (&fi, &p, type, objfile)
/* g++ does this next, but cfront already did this:
|| !read_struct_fields (&fi, &p, type, objfile) */
|| !attach_fields_to_type (&fi, type, objfile)
|| !read_cfront_member_functions (&fi, &p, type, objfile)
|| !attach_fn_fields_to_type (&fi, type)
/* g++ does this next, but cfront doesn't seem to have this:
|| !read_tilde_fields (&fi, &p, type, objfile) */
)
{
type = error_type (&p, objfile);
}
do_cleanups (back_to);
}
/* End of code added to support parsing of ARM/Cfront stabs strings */
/* ARGSUSED */
struct symbol *
define_symbol (valu, string, desc, type, objfile)
@ -1215,6 +1698,30 @@ define_symbol (valu, string, desc, type, objfile)
add_symbol_to_list (sym, &local_symbols);
break;
/* New code added to support cfront stabs strings */
/* Note: case 'P' already handled above */
case 'Z':
/* Cfront type continuation coming up!
find the original definition and add to it.
We'll have to do this for the typedef too,
since we clloned the symbol to define a type in read_type.
Stabs info examples:
__1C :Ztl
foo__1CFv :ZtF (first def foo__1CFv:F(0,3);(0,24))
C:ZsC;;__ct__1CFv func1__1CFv func2__1CFv ... ;;;
where C is the name of the class. */
/* can't lookup symbol yet 'cuz symbols not read yet
so we save it for processing later */
process_later(sym,p);
SYMBOL_TYPE (sym) = error_type (&p, objfile); /* FIXME! change later */
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_VALUE (sym) = 0;
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
/* don't add to list - we'll delete it later when
we add the continuation to the real sym */
return sym;
/* End of new code added to support cfront stabs strings */
default:
SYMBOL_TYPE (sym) = error_type (&p, objfile);
SYMBOL_CLASS (sym) = LOC_CONST;
@ -1349,7 +1856,6 @@ read_type (pp, objfile)
/* Skip the '='.
Also skip the type descriptor - we get it below with (*pp)[-1]. */
(*pp)+=2;
}
else
{
@ -1897,11 +2403,6 @@ rs6000_builtin_type (typenum)
/* This page contains subroutines of read_type. */
#define VISIBILITY_PRIVATE '0' /* Stabs character for private field */
#define VISIBILITY_PROTECTED '1' /* Stabs character for protected fld */
#define VISIBILITY_PUBLIC '2' /* Stabs character for public field */
#define VISIBILITY_IGNORE '9' /* Optimized out or zero length */
/* Read member function stabs info for C++ classes. The form of each member
function data is: